mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 02:43:14 +01:00
Merge dmd-1.073.
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -105,6 +105,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);
|
||||
@@ -275,6 +276,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
dmd/apply.c
Normal file
165
dmd/apply.c
Normal file
@@ -0,0 +1,165 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mars.h"
|
||||
#include "expression.h"
|
||||
|
||||
|
||||
/**************************************
|
||||
* An Expression tree walker that will visit each Expression e in the tree,
|
||||
* in depth-first evaluation order, and call fp(e,param) on it.
|
||||
* fp() signals whether the walking continues with its return value:
|
||||
* Returns:
|
||||
* 0 continue
|
||||
* 1 done
|
||||
* It's a bit slower than using virtual functions, but more encapsulated and less brittle.
|
||||
* Creating an iterator for this would be much more complex.
|
||||
*/
|
||||
|
||||
typedef int (*fp_t)(Expression *, void *);
|
||||
|
||||
int Expression::apply(fp_t fp, void *param)
|
||||
{
|
||||
return (*fp)(this, param);
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Perform apply() on an array of Expressions.
|
||||
*/
|
||||
|
||||
int arrayExpressionApply(Expressions *a, fp_t fp, void *param)
|
||||
{
|
||||
//printf("arrayExpressionApply(%p)\n", a);
|
||||
if (a)
|
||||
{
|
||||
for (size_t i = 0; i < a->dim; i++)
|
||||
{ Expression *e = (*a)[i];
|
||||
|
||||
if (e)
|
||||
{
|
||||
if (e->apply(fp, param))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NewExp::apply(int (*fp)(Expression *, void *), void *param)
|
||||
{
|
||||
//printf("NewExp::apply(): %s\n", toChars());
|
||||
|
||||
return ((thisexp ? thisexp->apply(fp, param) : 0) ||
|
||||
arrayExpressionApply(newargs, fp, param) ||
|
||||
arrayExpressionApply(arguments, fp, param) ||
|
||||
(*fp)(this, param));
|
||||
}
|
||||
|
||||
int NewAnonClassExp::apply(int (*fp)(Expression *, void *), void *param)
|
||||
{
|
||||
//printf("NewAnonClassExp::apply(): %s\n", toChars());
|
||||
|
||||
return ((thisexp ? thisexp->apply(fp, param) : 0) ||
|
||||
arrayExpressionApply(newargs, fp, param) ||
|
||||
arrayExpressionApply(arguments, fp, param) ||
|
||||
(*fp)(this, param));
|
||||
}
|
||||
|
||||
int UnaExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
return e1->apply(fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
int BinExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
return e1->apply(fp, param) ||
|
||||
e2->apply(fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
int AssertExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
|
||||
return e1->apply(fp, param) ||
|
||||
(msg ? msg->apply(fp, param) : 0) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int CallExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
|
||||
return e1->apply(fp, param) ||
|
||||
arrayExpressionApply(arguments, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int ArrayExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
//printf("ArrayExp::apply(fp_t fp, void *param): %s\n", toChars());
|
||||
return e1->apply(fp, param) ||
|
||||
arrayExpressionApply(arguments, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int SliceExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
return e1->apply(fp, param) ||
|
||||
(lwr ? lwr->apply(fp, param) : 0) ||
|
||||
(upr ? upr->apply(fp, param) : 0) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int ArrayLiteralExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
return arrayExpressionApply(elements, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int AssocArrayLiteralExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
return arrayExpressionApply(keys, fp, param) ||
|
||||
arrayExpressionApply(values, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int StructLiteralExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
return arrayExpressionApply(elements, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int TupleExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
return arrayExpressionApply(exps, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int CondExp::apply(fp_t fp, void *param)
|
||||
{
|
||||
return econd->apply(fp, param) ||
|
||||
e1->apply(fp, param) ||
|
||||
e2->apply(fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -551,7 +551,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; \
|
||||
}
|
||||
|
||||
|
||||
@@ -53,12 +53,21 @@ typedef ArrayBase<struct VarDeclaration> VarDeclarations;
|
||||
typedef ArrayBase<struct Type> Types;
|
||||
|
||||
typedef ArrayBase<struct ScopeDsymbol> ScopeDsymbols;
|
||||
|
||||
typedef ArrayBase<struct Catch> Catches;
|
||||
|
||||
typedef ArrayBase<struct StaticDtorDeclaration> StaticDtorDeclarations;
|
||||
|
||||
typedef ArrayBase<struct SharedStaticDtorDeclaration> SharedStaticDtorDeclarations;
|
||||
typedef ArrayBase<struct Module> Modules;
|
||||
typedef ArrayBase<struct CaseStatement> CaseStatements;
|
||||
|
||||
typedef ArrayBase<struct CompoundStatement> CompoundStatements;
|
||||
|
||||
typedef ArrayBase<struct GotoCaseStatement> GotoCaseStatements;
|
||||
|
||||
typedef ArrayBase<struct TemplateInstance> TemplateInstances;
|
||||
typedef ArrayBase<struct block> Blocks;
|
||||
|
||||
typedef ArrayBase<struct Symbol> Symbols;
|
||||
|
||||
|
||||
@@ -1142,6 +1142,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
else
|
||||
error("unrecognized pragma(%s)", ident->toChars());
|
||||
|
||||
Ldecl:
|
||||
if (decl)
|
||||
{
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
@@ -1159,7 +1160,10 @@ 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)
|
||||
|
||||
@@ -1451,10 +1451,14 @@ Expression *BinExp::typeCombine(Scope *sc)
|
||||
}
|
||||
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;
|
||||
}
|
||||
else if (t1->ty == Tclass || t2->ty == Tclass)
|
||||
|
||||
17
dmd/class.c
17
dmd/class.c
@@ -898,6 +898,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).
|
||||
|
||||
140
dmd/constfold.c
140
dmd/constfold.c
@@ -1244,7 +1244,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;
|
||||
}
|
||||
}
|
||||
@@ -1262,7 +1262,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;
|
||||
}
|
||||
}
|
||||
@@ -1282,7 +1282,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;
|
||||
}
|
||||
@@ -1335,7 +1335,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();
|
||||
@@ -1359,6 +1359,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)
|
||||
@@ -1468,62 +1526,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;
|
||||
|
||||
@@ -470,6 +470,7 @@ void AliasDeclaration::semantic(Scope *sc)
|
||||
#endif
|
||||
|
||||
storage_class |= sc->stc & STCdeprecated;
|
||||
protection = sc->protection;
|
||||
|
||||
// Given:
|
||||
// alias foo.bar.abc def;
|
||||
|
||||
@@ -291,10 +291,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
|
||||
@@ -717,15 +714,17 @@ struct FuncDeclaration : Declaration
|
||||
int vtblIndex; // for member functions, index into vtbl[]
|
||||
int naked; // !=0 if naked
|
||||
int inlineAsm; // !=0 if has inline assembler
|
||||
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
|
||||
int semanticRun; // 1 semantic() run
|
||||
// 2 semantic2() run
|
||||
// 3 semantic3() started
|
||||
// 4 semantic3() done
|
||||
// 5 toObjFile() run
|
||||
// this function's frame ptr
|
||||
int semantic3Errors; // !=0 if errors in semantic3
|
||||
ForeachStatement *fes; // if foreach body, this is the foreach
|
||||
int introducing; // !=0 if 'introducing' function
|
||||
Type *tintro; // if !=NULL, then this is the type
|
||||
@@ -803,18 +802,20 @@ struct FuncDeclaration : Declaration
|
||||
int isTrusted();
|
||||
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, Array *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();
|
||||
int needsClosure();
|
||||
int hasNestedFrameRefs();
|
||||
Statement *mergeFrequire(Statement *);
|
||||
Statement *mergeFensure(Statement *);
|
||||
Parameters *getParameters(int *pvarargs);
|
||||
@@ -854,9 +855,6 @@ struct FuncDeclaration : Declaration
|
||||
typedef std::map<const char*, LabelStatement*> LabelMap;
|
||||
LabelMap labmap;
|
||||
|
||||
// if this is an array operation it gets a little special attention
|
||||
bool isArrayOp;
|
||||
|
||||
// Functions that wouldn't have gotten semantic3'ed if we weren't inlining set this flag.
|
||||
bool availableExternally;
|
||||
|
||||
|
||||
232
dmd/delegatize.c
232
dmd/delegatize.c
@@ -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,180 +38,103 @@ 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 = new ReturnStatement(loc, e);
|
||||
Statement *s;
|
||||
if (t->ty == Tvoid)
|
||||
s = new ExpStatement(loc, e);
|
||||
else
|
||||
s = new ReturnStatement(loc, e);
|
||||
fld->fbody = s;
|
||||
e = new FuncExp(loc, fld);
|
||||
e = e->semantic(sc);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
12
dmd/doc.c
12
dmd/doc.c
@@ -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
|
||||
@@ -227,7 +227,7 @@ void Module::gendocfile()
|
||||
// Override with the ddoc macro files from the command line
|
||||
for (size_t i = 0; i < global.params.ddocfiles->dim; i++)
|
||||
{
|
||||
FileName f((char *)global.params.ddocfiles->data[i], 0);
|
||||
FileName f(global.params.ddocfiles->tdata()[i], 0);
|
||||
File file(&f);
|
||||
file.readv();
|
||||
// BUG: convert file contents to UTF-8 before use
|
||||
@@ -532,7 +532,7 @@ void ScopeDsymbol::emitMemberComments(Scope *sc)
|
||||
sc = sc->push(this);
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
//printf("\ts = '%s'\n", s->toChars());
|
||||
s->emitComment(sc);
|
||||
}
|
||||
@@ -704,7 +704,7 @@ void EnumDeclaration::emitComment(Scope *sc)
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
s->emitComment(sc);
|
||||
}
|
||||
return;
|
||||
@@ -962,7 +962,7 @@ void ClassDeclaration::toDocBuffer(OutBuffer *buf)
|
||||
}
|
||||
int any = 0;
|
||||
for (size_t i = 0; i < baseclasses->dim; i++)
|
||||
{ BaseClass *bc = (BaseClass *)baseclasses->data[i];
|
||||
{ BaseClass *bc = (*baseclasses)[i];
|
||||
|
||||
if (bc->protection == PROTprivate)
|
||||
continue;
|
||||
@@ -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++;
|
||||
|
||||
@@ -794,6 +794,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
|
||||
// Look in symbols declared in this module
|
||||
Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
|
||||
//printf("\ts = %p, imports = %p, %d\n", s, imports, imports ? imports->dim : 0);
|
||||
|
||||
// hide the aliases generated by selective or renamed private imports
|
||||
if (s && flags & 1)
|
||||
@@ -811,7 +812,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
|
||||
@@ -821,7 +822,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)
|
||||
@@ -850,7 +851,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
)
|
||||
)
|
||||
{
|
||||
ss->multiplyDefined(loc, s, s2);
|
||||
ScopeDsymbol::multiplyDefined(loc, s, s2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -859,14 +860,15 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
if (s)
|
||||
{
|
||||
Declaration *d = s->isDeclaration();
|
||||
if (d && d->protection == PROTprivate && !d->parent->isTemplateMixin())
|
||||
if (d && d->protection == PROTprivate &&
|
||||
!d->parent->isTemplateMixin())
|
||||
error(loc, "%s is private", d->toPrettyChars());
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -874,11 +876,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])
|
||||
@@ -995,8 +997,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
|
||||
@@ -1046,7 +1047,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;
|
||||
|
||||
@@ -285,14 +285,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);
|
||||
|
||||
306
dmd/expression.c
306
dmd/expression.c
@@ -746,11 +746,15 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
*/
|
||||
if (!tf->parameterEscapes(p))
|
||||
{
|
||||
Expression *a = arg;
|
||||
if (a->op == TOKcast)
|
||||
a = ((CastExp *)a)->e1;
|
||||
|
||||
/* Function literals can only appear once, so if this
|
||||
* appearance was scoped, there cannot be any others.
|
||||
*/
|
||||
if (arg->op == TOKfunction)
|
||||
{ FuncExp *fe = (FuncExp *)arg;
|
||||
if (a->op == TOKfunction)
|
||||
{ FuncExp *fe = (FuncExp *)a;
|
||||
fe->fd->tookAddressOf = 0;
|
||||
}
|
||||
|
||||
@@ -758,8 +762,8 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
* this doesn't count as taking the address of it.
|
||||
* We only worry about 'escaping' references to the function.
|
||||
*/
|
||||
else if (arg->op == TOKdelegate)
|
||||
{ DelegateExp *de = (DelegateExp *)arg;
|
||||
else if (a->op == TOKdelegate)
|
||||
{ DelegateExp *de = (DelegateExp *)a;
|
||||
if (de->e1->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)de->e1;
|
||||
FuncDeclaration *f = ve->var->isFuncDeclaration();
|
||||
@@ -1029,7 +1033,7 @@ void Expression::warning(const char *format, ...)
|
||||
}
|
||||
}
|
||||
|
||||
void Expression::rvalue()
|
||||
int Expression::rvalue()
|
||||
{
|
||||
if (type && type->toBasetype()->ty == Tvoid)
|
||||
{ error("expression %s is void and has no value", toChars());
|
||||
@@ -1037,8 +1041,11 @@ void Expression::rvalue()
|
||||
dump(0);
|
||||
halt();
|
||||
#endif
|
||||
type = Type::terror;
|
||||
if (!global.gag)
|
||||
type = Type::terror;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Expression *Expression::combine(Expression *e1, Expression *e2)
|
||||
@@ -1183,7 +1190,8 @@ Expression *Expression::checkIntegral()
|
||||
Expression *Expression::checkArithmetic()
|
||||
{
|
||||
if (!type->isintegral() && !type->isfloating())
|
||||
{ error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
|
||||
{ if (type->toBasetype() != Type::terror)
|
||||
error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
return this;
|
||||
@@ -2644,6 +2652,7 @@ StringExp::StringExp(Loc loc, char *string)
|
||||
this->sz = 1;
|
||||
this->committed = 0;
|
||||
this->postfix = 0;
|
||||
this->ownedByCtfe = false;
|
||||
}
|
||||
|
||||
StringExp::StringExp(Loc loc, void *string, size_t len)
|
||||
@@ -2654,6 +2663,7 @@ StringExp::StringExp(Loc loc, void *string, size_t len)
|
||||
this->sz = 1;
|
||||
this->committed = 0;
|
||||
this->postfix = 0;
|
||||
this->ownedByCtfe = false;
|
||||
}
|
||||
|
||||
StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix)
|
||||
@@ -2664,6 +2674,7 @@ StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix)
|
||||
this->sz = 1;
|
||||
this->committed = 0;
|
||||
this->postfix = postfix;
|
||||
this->ownedByCtfe = false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -2676,7 +2687,7 @@ Expression *StringExp::syntaxCopy()
|
||||
|
||||
int StringExp::equals(Object *o)
|
||||
{
|
||||
//printf("StringExp::equals('%s')\n", o->toChars());
|
||||
//printf("StringExp::equals('%s') %s\n", o->toChars(), toChars());
|
||||
if (o && o->dyncast() == DYNCAST_EXPRESSION)
|
||||
{ Expression *e = (Expression *)o;
|
||||
|
||||
@@ -2722,7 +2733,7 @@ Expression *StringExp::semantic(Scope *sc)
|
||||
p = utf_decodeChar((unsigned char *)string, len, &u, &c);
|
||||
if (p)
|
||||
{ error("%s", p);
|
||||
break;
|
||||
return new ErrorExp();
|
||||
}
|
||||
else
|
||||
{ buffer.write4(c);
|
||||
@@ -2743,7 +2754,7 @@ Expression *StringExp::semantic(Scope *sc)
|
||||
p = utf_decodeChar((unsigned char *)string, len, &u, &c);
|
||||
if (p)
|
||||
{ error("%s", p);
|
||||
break;
|
||||
return new ErrorExp();
|
||||
}
|
||||
else
|
||||
{ buffer.writeUTF16(c);
|
||||
@@ -3038,6 +3049,7 @@ ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
|
||||
: Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
|
||||
{
|
||||
this->elements = elements;
|
||||
this->ownedByCtfe = false;
|
||||
}
|
||||
|
||||
ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
|
||||
@@ -3116,9 +3128,9 @@ int ArrayLiteralExp::checkSideEffect(int flag)
|
||||
{ int f = 0;
|
||||
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = (Expression *)elements->data[i];
|
||||
{ Expression *e = elements->tdata()[i];
|
||||
|
||||
f |= e->checkSideEffect(2);
|
||||
f |= e->hasSideEffect();
|
||||
}
|
||||
if (flag == 0 && f == 0)
|
||||
Expression::checkSideEffect(0);
|
||||
@@ -3179,7 +3191,7 @@ void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
|
||||
size_t dim = elements ? elements->dim : 0;
|
||||
buf->printf("A%zu", dim);
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ Expression *e = (Expression *)elements->data[i];
|
||||
{ Expression *e = elements->tdata()[i];
|
||||
e->toMangleBuffer(buf);
|
||||
}
|
||||
}
|
||||
@@ -3195,6 +3207,7 @@ AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
|
||||
assert(keys->dim == values->dim);
|
||||
this->keys = keys;
|
||||
this->values = values;
|
||||
this->ownedByCtfe = false;
|
||||
}
|
||||
|
||||
Expression *AssocArrayLiteralExp::syntaxCopy()
|
||||
@@ -3238,8 +3251,8 @@ int AssocArrayLiteralExp::checkSideEffect(int flag)
|
||||
{ Expression *key = (Expression *)keys->data[i];
|
||||
Expression *value = (Expression *)values->data[i];
|
||||
|
||||
f |= key->checkSideEffect(2);
|
||||
f |= value->checkSideEffect(2);
|
||||
f |= key->hasSideEffect();
|
||||
f |= value->hasSideEffect();
|
||||
}
|
||||
if (flag == 0 && f == 0)
|
||||
Expression::checkSideEffect(0);
|
||||
@@ -3507,7 +3520,7 @@ int StructLiteralExp::checkSideEffect(int flag)
|
||||
if (!e)
|
||||
continue;
|
||||
|
||||
f |= e->checkSideEffect(2);
|
||||
f |= e->hasSideEffect();
|
||||
}
|
||||
if (flag == 0 && f == 0)
|
||||
Expression::checkSideEffect(0);
|
||||
@@ -3701,9 +3714,10 @@ void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writestring(td->toChars());
|
||||
}
|
||||
|
||||
void TemplateExp::rvalue()
|
||||
int TemplateExp::rvalue()
|
||||
{
|
||||
error("template %s has no value", toChars());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************** NewExp **************************************/
|
||||
@@ -3759,7 +3773,7 @@ Lagain:
|
||||
else
|
||||
{
|
||||
error("'this' for nested class must be a class type, not %s", thisexp->type->toChars());
|
||||
type = newtype->semantic(loc, sc);
|
||||
goto Lerr;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3774,7 +3788,9 @@ Lagain:
|
||||
preFunctionParameters(loc, sc, arguments);
|
||||
|
||||
if (thisexp && tb->ty != Tclass)
|
||||
error("e.new is only for allocating nested classes, not %s", tb->toChars());
|
||||
{ error("e.new is only for allocating nested classes, not %s", tb->toChars());
|
||||
goto Lerr;
|
||||
}
|
||||
|
||||
if (tb->ty == Tclass)
|
||||
{ TypeFunction *tf;
|
||||
@@ -3782,14 +3798,17 @@ Lagain:
|
||||
TypeClass *tc = (TypeClass *)(tb);
|
||||
ClassDeclaration *cd = tc->sym->isClassDeclaration();
|
||||
if (cd->isInterfaceDeclaration())
|
||||
error("cannot create instance of interface %s", cd->toChars());
|
||||
{ error("cannot create instance of interface %s", cd->toChars());
|
||||
goto Lerr;
|
||||
}
|
||||
else if (cd->isAbstract())
|
||||
{ error("cannot create instance of abstract class %s", cd->toChars());
|
||||
for (size_t i = 0; i < cd->vtbl.dim; i++)
|
||||
{ FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
|
||||
{ FuncDeclaration *fd = cd->vtbl.tdata()[i]->isFuncDeclaration();
|
||||
if (fd && fd->isAbstract())
|
||||
error("function %s is abstract", fd->toChars());
|
||||
}
|
||||
goto Lerr;
|
||||
}
|
||||
checkDeprecated(sc, cd);
|
||||
if (cd->isNested())
|
||||
@@ -3811,7 +3830,7 @@ Lagain:
|
||||
{ if (!sp)
|
||||
{
|
||||
error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
|
||||
break;
|
||||
goto Lerr;
|
||||
}
|
||||
ClassDeclaration *cdp = sp->isClassDeclaration();
|
||||
if (!cdp)
|
||||
@@ -3828,7 +3847,9 @@ Lagain:
|
||||
{
|
||||
//printf("cdthis = %s\n", cdthis->toChars());
|
||||
if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL))
|
||||
error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars());
|
||||
{ error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars());
|
||||
goto Lerr;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
@@ -3838,7 +3859,7 @@ Lagain:
|
||||
if (!sf)
|
||||
{
|
||||
error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
|
||||
break;
|
||||
goto Lerr;
|
||||
}
|
||||
printf("sf = %s\n", sf->toChars());
|
||||
AggregateDeclaration *ad = sf->isThis();
|
||||
@@ -3849,7 +3870,9 @@ Lagain:
|
||||
#endif
|
||||
}
|
||||
else if (thisexp)
|
||||
error("e.new is only for allocating nested classes");
|
||||
{ error("e.new is only for allocating nested classes");
|
||||
goto Lerr;
|
||||
}
|
||||
else if (fdn)
|
||||
{
|
||||
// make sure the parent context fdn of cd is reachable from sc
|
||||
@@ -3861,13 +3884,15 @@ Lagain:
|
||||
if (!sp || (fsp && fsp->isStatic()))
|
||||
{
|
||||
error("outer function context of %s is needed to 'new' nested class %s", fdn->toPrettyChars(), cd->toPrettyChars());
|
||||
break;
|
||||
goto Lerr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (thisexp)
|
||||
error("e.new is only for allocating nested classes");
|
||||
{ error("e.new is only for allocating nested classes");
|
||||
goto Lerr;
|
||||
}
|
||||
|
||||
FuncDeclaration *f = cd->ctor;
|
||||
if (f)
|
||||
@@ -3885,12 +3910,18 @@ Lagain:
|
||||
|
||||
if (!arguments)
|
||||
arguments = new Expressions();
|
||||
unsigned olderrors = global.errors;
|
||||
functionParameters(loc, sc, tf, arguments);
|
||||
if (olderrors != global.errors)
|
||||
return new ErrorExp();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arguments && arguments->dim)
|
||||
error("no constructor for %s", cd->toChars());
|
||||
{ error("no constructor for %s", cd->toChars());
|
||||
goto Lerr;
|
||||
}
|
||||
}
|
||||
|
||||
if (cd->aggNew)
|
||||
@@ -3906,12 +3937,18 @@ Lagain:
|
||||
assert(allocator);
|
||||
|
||||
tf = (TypeFunction *)f->type;
|
||||
unsigned olderrors = global.errors;
|
||||
functionParameters(loc, sc, tf, newargs);
|
||||
if (olderrors != global.errors)
|
||||
return new ErrorExp();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newargs && newargs->dim)
|
||||
error("no allocator for %s", cd->toChars());
|
||||
{ error("no allocator for %s", cd->toChars());
|
||||
goto Lerr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tb->ty == Tstruct)
|
||||
@@ -3939,7 +3976,10 @@ Lagain:
|
||||
assert(allocator);
|
||||
|
||||
tf = (TypeFunction *)f->type;
|
||||
unsigned olderrors = global.errors;
|
||||
functionParameters(loc, sc, tf, newargs);
|
||||
if (olderrors != global.errors)
|
||||
return new ErrorExp();
|
||||
|
||||
e = new VarExp(loc, f);
|
||||
e = new CallExp(loc, e, newargs);
|
||||
@@ -3956,36 +3996,42 @@ Lagain:
|
||||
{
|
||||
if (tb->ty != Tarray)
|
||||
{ error("too many arguments for array");
|
||||
arguments->dim = i;
|
||||
break;
|
||||
goto Lerr;
|
||||
}
|
||||
|
||||
Expression *arg = (Expression *)arguments->data[i];
|
||||
Expression *arg = arguments->tdata()[i];
|
||||
arg = resolveProperties(sc, arg);
|
||||
arg = arg->implicitCastTo(sc, Type::tsize_t);
|
||||
if (arg->op == TOKint64 && (long long)arg->toInteger() < 0)
|
||||
error("negative array index %s", arg->toChars());
|
||||
arguments->data[i] = (void *) arg;
|
||||
{ error("negative array index %s", arg->toChars());
|
||||
goto Lerr;
|
||||
}
|
||||
arguments->tdata()[i] = arg;
|
||||
tb = ((TypeDArray *)tb)->next->toBasetype();
|
||||
}
|
||||
}
|
||||
else if (tb->isscalar())
|
||||
{
|
||||
if (arguments && arguments->dim)
|
||||
error("no constructor for %s", type->toChars());
|
||||
{ error("no constructor for %s", type->toChars());
|
||||
goto Lerr;
|
||||
}
|
||||
|
||||
type = type->pointerTo();
|
||||
}
|
||||
else
|
||||
{
|
||||
error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars());
|
||||
type = type->pointerTo();
|
||||
goto Lerr;
|
||||
}
|
||||
|
||||
//printf("NewExp: '%s'\n", toChars());
|
||||
//printf("NewExp:type '%s'\n", type->toChars());
|
||||
|
||||
return this;
|
||||
|
||||
Lerr:
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
int NewExp::checkSideEffect(int flag)
|
||||
@@ -3994,9 +4040,24 @@ int NewExp::checkSideEffect(int flag)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int NewExp::canThrow()
|
||||
int NewExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
return 1;
|
||||
if (arrayExpressionCanThrow(newargs, mustNotThrow) ||
|
||||
arrayExpressionCanThrow(arguments, mustNotThrow))
|
||||
return 1;
|
||||
if (member)
|
||||
{
|
||||
// See if constructor call can throw
|
||||
Type *t = member->type->toBasetype();
|
||||
if (t->ty == Tfunction && !((TypeFunction *)t)->isnothrow)
|
||||
{
|
||||
if (mustNotThrow)
|
||||
error("constructor %s is not nothrow", member->toChars());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// regard storage allocation failures as not recoverable
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4499,7 +4560,7 @@ int TupleExp::checkSideEffect(int flag)
|
||||
for (size_t i = 0; i < exps->dim; i++)
|
||||
{ Expression *e = (*exps)[i];
|
||||
|
||||
f |= e->checkSideEffect(2);
|
||||
f |= e->hasSideEffect();
|
||||
}
|
||||
if (flag == 0 && f == 0)
|
||||
Expression::checkSideEffect(0);
|
||||
@@ -5027,17 +5088,13 @@ Expression *IsExp::semantic(Scope *sc)
|
||||
/* Declare trailing parameters
|
||||
*/
|
||||
for (size_t i = 1; i < parameters->dim; i++)
|
||||
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
|
||||
{ TemplateParameter *tp = (*parameters)[i];
|
||||
Declaration *s = NULL;
|
||||
|
||||
m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s);
|
||||
if (m == MATCHnomatch)
|
||||
goto Lno;
|
||||
s->semantic(sc);
|
||||
#if 0
|
||||
Object *o = (Object *)dedtypes.data[i];
|
||||
Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o);
|
||||
#endif
|
||||
if (sc->sd)
|
||||
s->addMember(sc, sc->sd, 1);
|
||||
else if (!sc->insert(s))
|
||||
@@ -5080,9 +5137,18 @@ Expression *IsExp::semantic(Scope *sc)
|
||||
Lyes:
|
||||
if (id)
|
||||
{
|
||||
Dsymbol *s = new AliasDeclaration(loc, id, tded);
|
||||
Dsymbol *s;
|
||||
Tuple *tup = isTuple(tded);
|
||||
if (tup)
|
||||
s = new TupleDeclaration(loc, id, &(tup->objects));
|
||||
else
|
||||
s = new AliasDeclaration(loc, id, tded);
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
/* The reason for the !tup is unclear. It fails Phobos unittests if it is not there.
|
||||
* More investigation is needed.
|
||||
*/
|
||||
if (!tup && !sc->insert(s))
|
||||
error("declaration %s is already defined", s->toChars());
|
||||
if (sc->sd)
|
||||
s->addMember(sc, sc->sd, 1);
|
||||
}
|
||||
@@ -5732,6 +5798,12 @@ Expression *DotIdExp::semantic(Scope *sc)
|
||||
(ie->sds->isModule() && ie->sds != sc->module) ? 1 : 0);
|
||||
if (s)
|
||||
{
|
||||
/* Check for access before resolving aliases because public
|
||||
* aliases to private symbols are public.
|
||||
*/
|
||||
if (Declaration *d = s->isDeclaration())
|
||||
accessCheck(loc, sc, 0, d);
|
||||
|
||||
s = s->toAlias();
|
||||
checkDeprecated(sc, s);
|
||||
|
||||
@@ -6606,7 +6678,15 @@ Lagain:
|
||||
}
|
||||
else
|
||||
{
|
||||
static int nest;
|
||||
if (++nest > 500)
|
||||
{
|
||||
error("recursive evaluation of %s", toChars());
|
||||
--nest;
|
||||
return new ErrorExp();
|
||||
}
|
||||
UnaExp::semantic(sc);
|
||||
--nest;
|
||||
|
||||
/* Look for e1 being a lazy parameter
|
||||
*/
|
||||
@@ -6627,6 +6707,14 @@ Lagain:
|
||||
e1 = new DsymbolExp(loc, se->sds);
|
||||
e1 = e1->semantic(sc);
|
||||
}
|
||||
#if DMDV2
|
||||
else if (e1->op == TOKsymoff && ((SymOffExp *)e1)->hasOverloads)
|
||||
{
|
||||
SymOffExp *se = (SymOffExp *)e1;
|
||||
e1 = new VarExp(se->loc, se->var, 1);
|
||||
e1 = e1->semantic(sc);
|
||||
}
|
||||
#endif
|
||||
#if 1 // patch for #540 by Oskar Linde
|
||||
else if (e1->op == TOKdotexp)
|
||||
{
|
||||
@@ -6754,9 +6842,7 @@ Lagain:
|
||||
arguments = new Expressions();
|
||||
f = td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
|
||||
if (!f)
|
||||
{ type = Type::terror;
|
||||
return this;
|
||||
}
|
||||
return new ErrorExp();
|
||||
ad = td->toParent()->isAggregateDeclaration();
|
||||
}
|
||||
if (f->needThis())
|
||||
@@ -6785,7 +6871,10 @@ Lagain:
|
||||
if (!f->needThis())
|
||||
{
|
||||
VarExp *ve = new VarExp(loc, f);
|
||||
e1 = new CommaExp(loc, ue->e1, ve);
|
||||
if ((ue->e1)->op == TOKtype) // just a FQN
|
||||
e1 = ve;
|
||||
else // things like (new Foo).bar()
|
||||
e1 = new CommaExp(loc, ue->e1, ve);
|
||||
e1->type = f->type;
|
||||
}
|
||||
else
|
||||
@@ -6823,16 +6912,14 @@ Lagain:
|
||||
if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration())
|
||||
{
|
||||
error("super class constructor call must be in a constructor");
|
||||
type = Type::terror;
|
||||
return this;
|
||||
return new ErrorExp();
|
||||
}
|
||||
else
|
||||
{
|
||||
f = cd->baseClass->ctor;
|
||||
if (!f)
|
||||
{ error("no super class constructor for %s", cd->baseClass->toChars());
|
||||
type = Type::terror;
|
||||
return this;
|
||||
return new ErrorExp();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6854,6 +6941,7 @@ Lagain:
|
||||
checkDeprecated(sc, f);
|
||||
#if DMDV2
|
||||
checkPurity(sc, f);
|
||||
checkSafety(sc, f);
|
||||
#endif
|
||||
e1 = new DotVarExp(e1->loc, e1, f);
|
||||
e1 = e1->semantic(sc);
|
||||
@@ -6871,8 +6959,7 @@ Lagain:
|
||||
if (!cd || !sc->func->isCtorDeclaration())
|
||||
{
|
||||
error("class constructor call must be in a constructor");
|
||||
type = Type::terror;
|
||||
return this;
|
||||
return new ErrorExp();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6894,6 +6981,7 @@ Lagain:
|
||||
checkDeprecated(sc, f);
|
||||
#if DMDV2
|
||||
checkPurity(sc, f);
|
||||
checkSafety(sc, f);
|
||||
#endif
|
||||
e1 = new DotVarExp(e1->loc, e1, f);
|
||||
e1 = e1->semantic(sc);
|
||||
@@ -6902,14 +6990,15 @@ Lagain:
|
||||
// BUG: this should really be done by checking the static
|
||||
// call graph
|
||||
if (f == sc->func)
|
||||
error("cyclic constructor call");
|
||||
{ error("cyclic constructor call");
|
||||
return new ErrorExp();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!t1)
|
||||
{
|
||||
error("function expected before (), not '%s'", e1->toChars());
|
||||
type = Type::terror;
|
||||
return this;
|
||||
return new ErrorExp();
|
||||
}
|
||||
else if (t1->ty != Tfunction)
|
||||
{
|
||||
@@ -6920,9 +7009,8 @@ Lagain:
|
||||
goto Lcheckargs;
|
||||
}
|
||||
else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
|
||||
{ Expression *e;
|
||||
|
||||
e = new PtrExp(loc, e1);
|
||||
{
|
||||
Expression *e = new PtrExp(loc, e1);
|
||||
t1 = ((TypePointer *)t1)->next;
|
||||
e->type = t1;
|
||||
e1 = e;
|
||||
@@ -6932,8 +7020,8 @@ Lagain:
|
||||
TemplateExp *te = (TemplateExp *)e1;
|
||||
f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
|
||||
if (!f)
|
||||
{ type = Type::terror;
|
||||
return this;
|
||||
{
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (f->needThis() && hasThis(sc))
|
||||
{
|
||||
@@ -6949,8 +7037,7 @@ Lagain:
|
||||
}
|
||||
else
|
||||
{ error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars());
|
||||
type = Type::terror;
|
||||
return this;
|
||||
return new ErrorExp();
|
||||
}
|
||||
}
|
||||
else if (e1->op == TOKvar)
|
||||
@@ -6988,6 +7075,7 @@ Lagain:
|
||||
checkDeprecated(sc, f);
|
||||
#if DMDV2
|
||||
checkPurity(sc, f);
|
||||
checkSafety(sc, f);
|
||||
#endif
|
||||
|
||||
if (f->needThis() && hasThis(sc))
|
||||
@@ -7014,9 +7102,16 @@ Lcheckargs:
|
||||
|
||||
if (!arguments)
|
||||
arguments = new Expressions();
|
||||
int olderrors = global.errors;
|
||||
functionParameters(loc, sc, tf, arguments);
|
||||
if (olderrors != global.errors)
|
||||
return new ErrorExp();
|
||||
|
||||
assert(type);
|
||||
if (!type)
|
||||
{
|
||||
error("forward reference to inferred return type of function call %s", toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
if (f && f->tintro)
|
||||
{
|
||||
@@ -7037,31 +7132,43 @@ Lcheckargs:
|
||||
int CallExp::checkSideEffect(int flag)
|
||||
{
|
||||
#if DMDV2
|
||||
if (flag != 2)
|
||||
return 1;
|
||||
int result = 1;
|
||||
|
||||
if (e1->checkSideEffect(2))
|
||||
return 1;
|
||||
/* Calling a function or delegate that is pure nothrow
|
||||
* has no side effects.
|
||||
*/
|
||||
if (e1->type)
|
||||
{
|
||||
Type *t = 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)
|
||||
)
|
||||
{
|
||||
result = 0;
|
||||
//if (flag == 0)
|
||||
//warning("pure nothrow function %s has no effect", e1->toChars());
|
||||
}
|
||||
else
|
||||
result = 1;
|
||||
}
|
||||
|
||||
result |= e1->checkSideEffect(1);
|
||||
|
||||
/* If any of the arguments have side effects, this expression does
|
||||
*/
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *e = (Expression *)arguments->data[i];
|
||||
{ Expression *e = arguments->tdata()[i];
|
||||
|
||||
if (e->checkSideEffect(2))
|
||||
return 1;
|
||||
result |= e->checkSideEffect(1);
|
||||
}
|
||||
|
||||
/* If calling a function or delegate that is typed as pure,
|
||||
* then this expression has no side effects.
|
||||
*/
|
||||
Type *t = e1->type->toBasetype();
|
||||
if (t->ty == Tfunction && ((TypeFunction *)t)->ispure)
|
||||
return 0;
|
||||
if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->ispure)
|
||||
return 0;
|
||||
#endif
|
||||
return result;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
@@ -7284,7 +7391,8 @@ Expression *PtrExp::semantic(Scope *sc)
|
||||
case Terror:
|
||||
return new ErrorExp();
|
||||
}
|
||||
rvalue();
|
||||
if (!rvalue())
|
||||
return new ErrorExp();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -8166,7 +8274,7 @@ int CommaExp::isBool(int result)
|
||||
int CommaExp::checkSideEffect(int flag)
|
||||
{
|
||||
if (flag == 2)
|
||||
return e1->checkSideEffect(2) || e2->checkSideEffect(2);
|
||||
return e1->hasSideEffect() || e2->hasSideEffect();
|
||||
else
|
||||
{
|
||||
// Don't check e1 until we cast(void) the a,b code generation
|
||||
@@ -8585,7 +8693,8 @@ Expression *AssignExp::semantic(Scope *sc)
|
||||
}
|
||||
}
|
||||
|
||||
e2->rvalue();
|
||||
if (!e2->rvalue())
|
||||
return new ErrorExp();
|
||||
|
||||
if (e1->op == TOKarraylength)
|
||||
{
|
||||
@@ -8628,12 +8737,22 @@ Expression *AssignExp::semantic(Scope *sc)
|
||||
e2->op == TOKmul || e2->op == TOKdiv ||
|
||||
e2->op == TOKmod || e2->op == TOKxor ||
|
||||
e2->op == TOKand || e2->op == TOKor ||
|
||||
#if DMDV2
|
||||
e2->op == TOKpow ||
|
||||
#endif
|
||||
e2->op == TOKtilde || e2->op == TOKneg))
|
||||
{
|
||||
type = e1->type;
|
||||
return arrayOp(sc);
|
||||
}
|
||||
|
||||
if (e1->op == TOKvar &&
|
||||
(((VarExp *)e1)->var->storage_class & STCscope) &&
|
||||
op == TOKassign)
|
||||
{
|
||||
error("cannot rebind scope variables");
|
||||
}
|
||||
|
||||
type = e1->type;
|
||||
assert(type);
|
||||
return this;
|
||||
@@ -8646,7 +8765,7 @@ Expression *AssignExp::checkToBoolean()
|
||||
// are usually mistakes.
|
||||
|
||||
error("assignment cannot be used as a condition, perhaps == was meant?");
|
||||
return this;
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
@@ -8853,7 +8972,8 @@ Expression *CatAssignExp::semantic(Scope *sc)
|
||||
Type *tb1 = e1->type->toBasetype();
|
||||
Type *tb2 = e2->type->toBasetype();
|
||||
|
||||
e2->rvalue();
|
||||
if (!e2->rvalue())
|
||||
return new ErrorExp();
|
||||
|
||||
Type *tb1next = tb1->nextOf();
|
||||
|
||||
@@ -9889,7 +10009,7 @@ int OrOrExp::checkSideEffect(int flag)
|
||||
{
|
||||
if (flag == 2)
|
||||
{
|
||||
return e1->checkSideEffect(2) || e2->checkSideEffect(2);
|
||||
return e1->hasSideEffect() || e2->hasSideEffect();
|
||||
}
|
||||
else
|
||||
{ e1->checkSideEffect(1);
|
||||
@@ -9964,7 +10084,7 @@ int AndAndExp::checkSideEffect(int flag)
|
||||
{
|
||||
if (flag == 2)
|
||||
{
|
||||
return e1->checkSideEffect(2) || e2->checkSideEffect(2);
|
||||
return e1->hasSideEffect() || e2->hasSideEffect();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -10422,9 +10542,9 @@ int CondExp::checkSideEffect(int flag)
|
||||
{
|
||||
if (flag == 2)
|
||||
{
|
||||
return econd->checkSideEffect(2) ||
|
||||
e1->checkSideEffect(2) ||
|
||||
e2->checkSideEffect(2);
|
||||
return econd->hasSideEffect() ||
|
||||
e1->hasSideEffect() ||
|
||||
e2->hasSideEffect();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -74,6 +74,8 @@ 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);
|
||||
Dsymbol *search_function(AggregateDeclaration *ad, Identifier *funcid);
|
||||
@@ -111,6 +113,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);
|
||||
|
||||
@@ -121,7 +124,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);
|
||||
@@ -153,7 +156,6 @@ struct Expression : Object
|
||||
Expression *integralPromotions(Scope *sc);
|
||||
|
||||
Expression *toDelegate(Scope *sc, Type *t);
|
||||
virtual void scanForNestedRef(Scope *sc);
|
||||
|
||||
virtual Expression *optimize(int result);
|
||||
#define WANTflags 1
|
||||
@@ -168,10 +170,11 @@ struct Expression : Object
|
||||
virtual int isConst();
|
||||
virtual int isBool(int result);
|
||||
virtual int isBit();
|
||||
bool hasSideEffect();
|
||||
virtual int checkSideEffect(int flag);
|
||||
virtual int canThrow();
|
||||
|
||||
virtual int inlineCost(InlineCostState *ics);
|
||||
virtual int inlineCost3(InlineCostState *ics);
|
||||
virtual Expression *doInline(InlineDoState *ids);
|
||||
virtual Expression *inlineScan(InlineScanState *iss);
|
||||
Expression *inlineCopy(Scope *sc);
|
||||
@@ -342,9 +345,8 @@ struct ThisExp : Expression
|
||||
int isBool(int result);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
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);
|
||||
|
||||
@@ -362,9 +364,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);
|
||||
};
|
||||
@@ -399,6 +399,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);
|
||||
@@ -436,10 +437,10 @@ 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);
|
||||
@@ -449,7 +450,6 @@ struct TupleExp : Expression
|
||||
elem *toElem(IRState *irs);
|
||||
#endif
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -461,24 +461,24 @@ 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 inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -495,10 +495,12 @@ 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
|
||||
@@ -507,13 +509,11 @@ struct AssocArrayLiteralExp : Expression
|
||||
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 inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -535,22 +535,23 @@ 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);
|
||||
Expression *toLvalue(Scope *sc, Expression *e);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
int inlineCost3(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -610,7 +611,7 @@ struct TemplateExp : Expression
|
||||
TemplateDeclaration *td;
|
||||
|
||||
TemplateExp(Loc loc, TemplateDeclaration *td);
|
||||
void rvalue();
|
||||
int rvalue();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
@@ -630,6 +631,7 @@ 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);
|
||||
@@ -638,9 +640,8 @@ struct NewExp : Expression
|
||||
#endif
|
||||
int checkSideEffect(int flag);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
|
||||
//int inlineCost(InlineCostState *ics);
|
||||
//int inlineCost3(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
//Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -661,6 +662,7 @@ 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);
|
||||
@@ -696,7 +698,6 @@ struct SymOffExp : Expression
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
@@ -731,9 +732,7 @@ struct VarExp : Expression
|
||||
elem *toElem(IRState *irs);
|
||||
dt_t **toDt(dt_t **pdt);
|
||||
#endif
|
||||
void scanForNestedRef(Scope *sc);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
//Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -767,7 +766,6 @@ struct FuncExp : Expression
|
||||
Expression *syntaxCopy();
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
char *toChars();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
#if IN_DMD
|
||||
@@ -775,7 +773,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);
|
||||
|
||||
@@ -800,9 +798,8 @@ struct DeclarationExp : Expression
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
#endif
|
||||
void scanForNestedRef(Scope *sc);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
int inlineCost3(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -875,14 +872,13 @@ 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 inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -896,6 +892,7 @@ 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);
|
||||
Expression *commonSemanticAssign(Scope *sc);
|
||||
@@ -910,7 +907,6 @@ struct BinExp : Expression
|
||||
int isunsigned();
|
||||
void 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,
|
||||
@@ -919,7 +915,6 @@ struct BinExp : Expression
|
||||
Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
|
||||
Expression *arrayOp(Scope *sc);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -958,12 +953,12 @@ 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);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -1040,7 +1035,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
|
||||
@@ -1076,6 +1071,7 @@ struct CallExp : UnaExp
|
||||
CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2);
|
||||
|
||||
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);
|
||||
@@ -1085,11 +1081,10 @@ struct CallExp : UnaExp
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
#endif
|
||||
void scanForNestedRef(Scope *sc);
|
||||
Expression *toLvalue(Scope *sc, Expression *e);
|
||||
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
int inlineCost3(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -1276,6 +1271,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();
|
||||
@@ -1289,12 +1285,10 @@ 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();
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -1328,15 +1322,14 @@ struct ArrayExp : UnaExp
|
||||
|
||||
ArrayExp(Loc loc, Expression *e1, Expressions *arguments);
|
||||
Expression *syntaxCopy();
|
||||
int apply(apply_fp_t fp, void *param);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *toLvalue(Scope *sc, Expression *e);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
|
||||
// For operator overloading
|
||||
Identifier *opId();
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
};
|
||||
@@ -1385,7 +1378,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);
|
||||
@@ -1899,6 +1891,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);
|
||||
@@ -1911,9 +1904,7 @@ struct CondExp : BinExp
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -2015,4 +2006,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 */
|
||||
|
||||
92
dmd/func.c
92
dmd/func.c
@@ -61,11 +61,13 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
|
||||
vtblIndex = -1;
|
||||
hasReturnExp = 0;
|
||||
naked = 0;
|
||||
inlineStatus = ILSuninitialized;
|
||||
inlineStatusExp = ILSuninitialized;
|
||||
inlineStatusStmt = ILSuninitialized;
|
||||
inlineNest = 0;
|
||||
inlineAsm = 0;
|
||||
cantInterpret = 0;
|
||||
isArrayOp = 0;
|
||||
semanticRun = PASSinit;
|
||||
semantic3Errors = 0;
|
||||
#if DMDV1
|
||||
nestedFrameRef = 0;
|
||||
#endif
|
||||
@@ -86,6 +88,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
|
||||
#if DMDV2
|
||||
builtin = BUILTINunknown;
|
||||
tookAddressOf = 0;
|
||||
flags = 0;
|
||||
#endif
|
||||
|
||||
#if IN_LLVM
|
||||
@@ -408,7 +411,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
return;
|
||||
|
||||
default:
|
||||
{ FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl.data[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());
|
||||
@@ -422,11 +425,13 @@ 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 is mixin) && (fdc is not mixin) then fdc overrides
|
||||
if (!this->parent->isClassDeclaration() && fdc->parent->isClassDeclaration())
|
||||
break;
|
||||
if (!this->parent->isClassDeclaration()
|
||||
|
||||
if (!this->parent->isClassDeclaration() // if both are mixins then error
|
||||
#if !BREAKABI
|
||||
&& !isDtorDeclaration()
|
||||
#endif
|
||||
@@ -726,6 +731,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
if (semanticRun >= PASSsemantic3)
|
||||
return;
|
||||
semanticRun = PASSsemantic3;
|
||||
semantic3Errors = 0;
|
||||
|
||||
#if IN_LLVM
|
||||
if (!global.params.useAvailableExternally)
|
||||
@@ -847,7 +853,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 std.c.stdarg to use variadic functions");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL);
|
||||
@@ -1560,7 +1569,12 @@ 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);
|
||||
}
|
||||
|
||||
void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
@@ -1575,7 +1589,7 @@ void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
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();
|
||||
|
||||
@@ -1667,11 +1681,11 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf)
|
||||
Statement *s2 = new ExpStatement(loc, e);
|
||||
|
||||
Catch *c = new Catch(loc, NULL, NULL, sf);
|
||||
Array *catches = new Array();
|
||||
catches->push(c);
|
||||
sf = new TryCatchStatement(loc, s2, catches);
|
||||
}
|
||||
else
|
||||
Catches *catches = new Catches();
|
||||
catches->push(c);
|
||||
sf = new TryCatchStatement(loc, s2, catches);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
return sf;
|
||||
@@ -2448,6 +2462,21 @@ int FuncDeclaration::isVirtual()
|
||||
toParent()->isClassDeclaration();
|
||||
}
|
||||
|
||||
// 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;
|
||||
@@ -2622,6 +2651,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.
|
||||
|
||||
165
dmd/import.c
165
dmd/import.c
@@ -27,7 +27,7 @@
|
||||
|
||||
Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId,
|
||||
int isstatic)
|
||||
: Dsymbol(id)
|
||||
: Dsymbol()
|
||||
{
|
||||
assert(id);
|
||||
this->loc = loc;
|
||||
@@ -38,12 +38,6 @@ Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *alias
|
||||
protection = PROTundefined;
|
||||
pkg = NULL;
|
||||
mod = NULL;
|
||||
|
||||
if (aliasId)
|
||||
this->ident = aliasId;
|
||||
// Kludge to change Import identifier to first package
|
||||
else if (packages && packages->dim)
|
||||
this->ident = (Identifier *)packages->data[0];
|
||||
}
|
||||
|
||||
void Import::addAlias(Identifier *name, Identifier *alias)
|
||||
@@ -51,9 +45,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);
|
||||
}
|
||||
@@ -72,13 +63,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((Identifier *)names.data[i], (Identifier *)aliases.data[i]);
|
||||
si->addAlias(names[i], aliases[i]);
|
||||
}
|
||||
|
||||
return si;
|
||||
@@ -146,15 +135,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,32 +172,31 @@ void Import::semantic(Scope *sc)
|
||||
|
||||
/* Default to private importing
|
||||
*/
|
||||
protection = sc->protection;
|
||||
enum PROT prot = sc->protection;
|
||||
if (!sc->explicitProtection)
|
||||
protection = PROTprivate;
|
||||
|
||||
if (!isstatic && !aliasId && !names.dim)
|
||||
prot = PROTprivate;
|
||||
for (Scope *scd = sc; scd; scd = scd->enclosing)
|
||||
{
|
||||
sc->scopesym->importScope(mod, protection);
|
||||
if (scd->scopesym)
|
||||
{
|
||||
scd->scopesym->importScope(this, prot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mod->semantic();
|
||||
|
||||
if (mod->needmoduleinfo)
|
||||
{ //printf("module4 %s because of %s\n", sc->module->toChars(), mod->toChars());
|
||||
sc->module->needmoduleinfo = 1;
|
||||
}
|
||||
|
||||
sc = sc->push(mod);
|
||||
for (size_t i = 0; i < aliasdecls.dim; i++)
|
||||
{ AliasDeclaration *ad = (AliasDeclaration *)aliasdecls.data[i];
|
||||
|
||||
//printf("\tImport alias semantic('%s')\n", s->toChars());
|
||||
if (!mod->search(loc, (Identifier *)names.data[i], 0))
|
||||
error("%s not found", ((Identifier *)names.data[i])->toChars());
|
||||
|
||||
ad->importprot = protection;
|
||||
if (aliasId)
|
||||
{
|
||||
AliasDeclaration *ad = new AliasDeclaration(loc, aliasId, mod);
|
||||
sc->insert(ad);
|
||||
ad->semantic(sc);
|
||||
}
|
||||
sc = sc->pop();
|
||||
}
|
||||
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
|
||||
|
||||
@@ -246,7 +231,7 @@ void Import::semantic(Scope *sc)
|
||||
{
|
||||
for (size_t i = 0; i < packages->dim; i++)
|
||||
{
|
||||
Identifier *pid = (Identifier *)packages->data[i];
|
||||
Identifier *pid = (*packages)[i];
|
||||
ob->printf("%s.", pid->toChars());
|
||||
}
|
||||
}
|
||||
@@ -266,8 +251,8 @@ void Import::semantic(Scope *sc)
|
||||
else
|
||||
ob->writebyte(',');
|
||||
|
||||
Identifier *name = (Identifier *)names.data[i];
|
||||
Identifier *alias = (Identifier *)aliases.data[i];
|
||||
Identifier *name = names[i];
|
||||
Identifier *alias = aliases[i];
|
||||
|
||||
if (!alias)
|
||||
{
|
||||
@@ -292,49 +277,9 @@ void Import::semantic2(Scope *sc)
|
||||
//printf("Import::semantic2('%s')\n", toChars());
|
||||
mod->semantic2();
|
||||
if (mod->needmoduleinfo)
|
||||
{ //printf("module5 %s because of %s\n", sc->module->toChars(), mod->toChars());
|
||||
sc->module->needmoduleinfo = 1;
|
||||
}
|
||||
|
||||
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 = (Identifier *)names.data[i];
|
||||
Identifier *alias = (Identifier *)aliases.data[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)
|
||||
@@ -346,14 +291,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)
|
||||
@@ -371,7 +352,7 @@ void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
if (packages && packages->dim)
|
||||
{
|
||||
for (size_t i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = (Identifier *)packages->data[i];
|
||||
{ Identifier *pid = (*packages)[i];
|
||||
|
||||
buf->printf("%s.", pid->toChars());
|
||||
}
|
||||
@@ -400,3 +381,7 @@ void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
char *Import::toChars()
|
||||
{
|
||||
return id->toChars();
|
||||
}
|
||||
|
||||
15
dmd/import.h
15
dmd/import.h
@@ -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,17 +28,16 @@ struct HdrGenState;
|
||||
|
||||
struct Import : Dsymbol
|
||||
{
|
||||
Identifiers *packages; // array of Identifier's representing packages
|
||||
// isstatic import aliasId = packages.id;
|
||||
Identifiers *packages; // array of Identifier's representing packages
|
||||
Identifier *id; // module Identifier
|
||||
Identifier *aliasId;
|
||||
int isstatic; // !=0 if static import
|
||||
enum PROT protection;
|
||||
|
||||
// Pairs of alias=name to bind into current namespace
|
||||
Array names;
|
||||
Array aliases;
|
||||
|
||||
Array aliasdecls; // AliasDeclarations for names/aliases
|
||||
Identifiers names;
|
||||
Identifiers aliases;
|
||||
|
||||
Module *mod;
|
||||
Package *pkg; // leftmost package/module
|
||||
@@ -54,11 +53,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; }
|
||||
};
|
||||
|
||||
14
dmd/init.c
14
dmd/init.c
@@ -164,8 +164,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
#endif
|
||||
for (size_t i = 0; i < field.dim; i++)
|
||||
{
|
||||
Identifier *id = (Identifier *)field.data[i];
|
||||
Initializer *val = (Initializer *)value.data[i];
|
||||
Identifier *id = field[i];
|
||||
Initializer *val = value[i];
|
||||
Dsymbol *s;
|
||||
VarDeclaration *v;
|
||||
|
||||
@@ -180,7 +180,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
}
|
||||
else
|
||||
{
|
||||
s = (Dsymbol *)ad->fields.data[fieldi];
|
||||
s = ad->fields[fieldi];
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -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++)
|
||||
@@ -204,7 +205,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
errors = 1;
|
||||
break;
|
||||
}
|
||||
if (s == (Dsymbol *)ad->fields.data[fieldi])
|
||||
if (s == ad->fields[fieldi])
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -277,7 +278,7 @@ Expression *StructInitializer::toExpression()
|
||||
unsigned fieldi = 0;
|
||||
for (size_t i = 0; i < value.dim; i++)
|
||||
{
|
||||
Identifier *id = (Identifier *)field.data[i];
|
||||
Identifier *id = field[i];
|
||||
if (id)
|
||||
{
|
||||
Dsymbol * s = ad->search(loc, id, 0);
|
||||
@@ -286,6 +287,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++)
|
||||
@@ -295,7 +297,7 @@ Expression *StructInitializer::toExpression()
|
||||
s->error("is not a per-instance initializable field");
|
||||
goto Lno;
|
||||
}
|
||||
if (s == (Dsymbol *)ad->fields.data[fieldi])
|
||||
if (s == ad->fields[fieldi])
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
525
dmd/inline.c
525
dmd/inline.c
@@ -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,41 +152,67 @@ 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
//printf("VarExp::inlineCost() %s\n", toChars());
|
||||
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;
|
||||
@@ -176,64 +223,38 @@ 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;
|
||||
#endif
|
||||
return 1 + arrayInlineCost(ics, elements);
|
||||
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.
|
||||
// Right now, this makes the function be output to the .obj file twice.
|
||||
return COST_MAX;
|
||||
}
|
||||
|
||||
int DelegateExp::inlineCost(InlineCostState *ics)
|
||||
int DelegateExp::inlineCost3(InlineCostState *ics)
|
||||
{
|
||||
//printf("DelegateExp::inlineCost3()\n");
|
||||
// This breaks on LDC too, since nested functions have internal linkage
|
||||
// and thus can't be referenced from other objects.
|
||||
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)
|
||||
{
|
||||
@@ -260,6 +281,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)
|
||||
{
|
||||
@@ -267,7 +292,7 @@ int DeclarationExp::inlineCost(InlineCostState *ics)
|
||||
|
||||
if (ie)
|
||||
{
|
||||
cost += ie->exp->inlineCost(ics);
|
||||
cost += expressionInlineCost(ie->exp, ics);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,82 +304,157 @@ 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)
|
||||
int CallExp::inlineCost3(InlineCostState *ics)
|
||||
{
|
||||
return 1 + e1->inlineCost(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;
|
||||
}
|
||||
|
||||
int AssertExp::inlineCost(InlineCostState *ics)
|
||||
|
||||
/* ======================== Perform the inlining ============================== */
|
||||
|
||||
/* Inlining is done by:
|
||||
* o Converting to an Expression
|
||||
* o Copying the trees of the function to be inlined
|
||||
* o Renaming the variables
|
||||
*/
|
||||
|
||||
struct InlineDoState
|
||||
{
|
||||
return 1 + e1->inlineCost(ics) + (msg ? msg->inlineCost(ics) : 0);
|
||||
VarDeclaration *vthis;
|
||||
Dsymbols from; // old Dsymbols
|
||||
Dsymbols to; // parallel array of new Dsymbols
|
||||
Dsymbol *parent; // new parent
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
Statement *Statement::doInlineStatement(InlineDoState *ids)
|
||||
{
|
||||
assert(0);
|
||||
return NULL; // default is we can't inline it
|
||||
}
|
||||
|
||||
int BinExp::inlineCost(InlineCostState *ics)
|
||||
Statement *ExpStatement::doInlineStatement(InlineDoState *ids)
|
||||
{
|
||||
return 1 + e1->inlineCost(ics) + e2->inlineCost(ics);
|
||||
#if LOG
|
||||
if (exp) printf("ExpStatement::doInlineStatement() '%s'\n", exp->toChars());
|
||||
#endif
|
||||
return new ExpStatement(loc, exp ? exp->doInline(ids) : NULL);
|
||||
}
|
||||
|
||||
int CallExp::inlineCost(InlineCostState *ics)
|
||||
{
|
||||
// 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;
|
||||
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;
|
||||
|
||||
return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
int ArrayExp::inlineCost(InlineCostState *ics)
|
||||
Statement *ScopeStatement::doInlineStatement(InlineDoState *ids)
|
||||
{
|
||||
return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
|
||||
//printf("ScopeStatement::doInlineStatement() %d\n", statements->dim);
|
||||
return statement ? new ScopeStatement(loc, statement->doInlineStatement(ids)) : this;
|
||||
}
|
||||
|
||||
Statement *IfStatement::doInlineStatement(InlineDoState *ids)
|
||||
{
|
||||
assert(!arg);
|
||||
|
||||
int CondExp::inlineCost(InlineCostState *ics)
|
||||
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)
|
||||
{
|
||||
return 1 +
|
||||
e1->inlineCost(ics) +
|
||||
e2->inlineCost(ics) +
|
||||
econd->inlineCost(ics);
|
||||
}
|
||||
|
||||
|
||||
/* ======================== Perform the inlining ============================== */
|
||||
|
||||
/* Inlining is done by:
|
||||
* o Converting to an Expression
|
||||
* o Copying the trees of the function to be inlined
|
||||
* o Renaming the variables
|
||||
*/
|
||||
|
||||
struct InlineDoState
|
||||
{
|
||||
VarDeclaration *vthis;
|
||||
Array from; // old Dsymbols
|
||||
Array to; // parallel array of new Dsymbols
|
||||
Dsymbol *parent; // new parent
|
||||
};
|
||||
//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
|
||||
}
|
||||
@@ -417,6 +517,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;
|
||||
@@ -463,6 +568,13 @@ Expression *ReturnStatement::doInline(InlineDoState *ids)
|
||||
return exp ? exp->doInline(ids) : 0;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
Expression *ImportStatement::doInline(InlineDoState *ids)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
/******************************
|
||||
@@ -478,11 +590,11 @@ Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids)
|
||||
newa->setDim(a->dim);
|
||||
|
||||
for (size_t i = 0; i < a->dim; i++)
|
||||
{ Expression *e = (Expression *)a->data[i];
|
||||
{ Expression *e = a->tdata()[i];
|
||||
|
||||
if (e)
|
||||
e = e->doInline(ids);
|
||||
newa->data[i] = (void *)e;
|
||||
newa->tdata()[i] = e;
|
||||
}
|
||||
}
|
||||
return newa;
|
||||
@@ -499,11 +611,11 @@ Expression *SymOffExp::doInline(InlineDoState *ids)
|
||||
//printf("SymOffExp::doInline(%s)\n", toChars());
|
||||
for (size_t i = 0; i < ids->from.dim; i++)
|
||||
{
|
||||
if (var == (Declaration *)ids->from.data[i])
|
||||
if (var == ids->from.tdata()[i])
|
||||
{
|
||||
SymOffExp *se = (SymOffExp *)copy();
|
||||
|
||||
se->var = (Declaration *)ids->to.data[i];
|
||||
se->var = (Declaration *)ids->to.tdata()[i];
|
||||
return se;
|
||||
}
|
||||
}
|
||||
@@ -515,11 +627,11 @@ Expression *VarExp::doInline(InlineDoState *ids)
|
||||
//printf("VarExp::doInline(%s)\n", toChars());
|
||||
for (size_t i = 0; i < ids->from.dim; i++)
|
||||
{
|
||||
if (var == (Declaration *)ids->from.data[i])
|
||||
if (var == ids->from.tdata()[i])
|
||||
{
|
||||
VarExp *ve = (VarExp *)copy();
|
||||
|
||||
ve->var = (Declaration *)ids->to.data[i];
|
||||
ve->var = (Declaration *)ids->to.tdata()[i];
|
||||
return ve;
|
||||
}
|
||||
}
|
||||
@@ -563,7 +675,7 @@ Expression *DeclarationExp::doInline(InlineDoState *ids)
|
||||
if (td)
|
||||
{
|
||||
for (size_t i = 0; i < td->objects->dim; i++)
|
||||
{ DsymbolExp *se = (DsymbolExp *)td->objects->data[i];
|
||||
{ DsymbolExp *se = td->objects->tdata()[i];
|
||||
assert(se->op == TOKdsymbol);
|
||||
se->s;
|
||||
}
|
||||
@@ -825,16 +937,38 @@ 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;
|
||||
}
|
||||
|
||||
Statement *CompoundStatement::inlineScan(InlineScanState *iss)
|
||||
{
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s)
|
||||
statements->data[i] = (void *)s->inlineScan(iss);
|
||||
(*statements)[i] = s->inlineScan(iss);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -842,9 +976,9 @@ Statement *CompoundStatement::inlineScan(InlineScanState *iss)
|
||||
Statement *UnrolledLoopStatement::inlineScan(InlineScanState *iss)
|
||||
{
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s)
|
||||
statements->data[i] = (void *)s->inlineScan(iss);
|
||||
(*statements)[i] = s->inlineScan(iss);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -928,10 +1062,10 @@ Statement *SwitchStatement::inlineScan(InlineScanState *iss)
|
||||
if (cases)
|
||||
{
|
||||
for (size_t i = 0; i < cases->dim; i++)
|
||||
{ Statement *s;
|
||||
{ CaseStatement *s;
|
||||
|
||||
s = (Statement *) cases->data[i];
|
||||
cases->data[i] = (void *)s->inlineScan(iss);
|
||||
s = cases->tdata()[i];
|
||||
cases->tdata()[i] = (CaseStatement *)s->inlineScan(iss);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@@ -994,7 +1128,7 @@ Statement *TryCatchStatement::inlineScan(InlineScanState *iss)
|
||||
if (catches)
|
||||
{
|
||||
for (size_t i = 0; i < catches->dim; i++)
|
||||
{ Catch *c = (Catch *)catches->data[i];
|
||||
{ Catch *c = catches->tdata()[i];
|
||||
|
||||
if (c->handler)
|
||||
c->handler = c->handler->inlineScan(iss);
|
||||
@@ -1039,17 +1173,17 @@ Statement *LabelStatement::inlineScan(InlineScanState *iss)
|
||||
|
||||
/* -------------------------- */
|
||||
|
||||
void arrayInlineScan(InlineScanState *iss, Array *arguments)
|
||||
void arrayInlineScan(InlineScanState *iss, Expressions *arguments)
|
||||
{
|
||||
if (arguments)
|
||||
{
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *e = (Expression *)arguments->data[i];
|
||||
{ Expression *e = arguments->tdata()[i];
|
||||
|
||||
if (e)
|
||||
{
|
||||
e = e->inlineScan(iss);
|
||||
arguments->data[i] = (void *)e;
|
||||
arguments->tdata()[i] = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1069,7 +1203,7 @@ void scanVar(Dsymbol *s, InlineScanState *iss)
|
||||
if (td)
|
||||
{
|
||||
for (size_t i = 0; i < td->objects->dim; i++)
|
||||
{ DsymbolExp *se = (DsymbolExp *)td->objects->data[i];
|
||||
{ DsymbolExp *se = (DsymbolExp *)td->objects->tdata()[i];
|
||||
assert(se->op == TOKdsymbol);
|
||||
scanVar(se->s, iss);
|
||||
}
|
||||
@@ -1156,9 +1290,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)
|
||||
@@ -1166,7 +1300,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)
|
||||
@@ -1178,7 +1312,7 @@ Expression *CallExp::inlineScan(InlineScanState *iss)
|
||||
;
|
||||
}
|
||||
else
|
||||
e = fd->doInline(iss, dve->e1, arguments);
|
||||
e = fd->expandInline(iss, dve->e1, arguments, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1269,7 +1403,7 @@ void FuncDeclaration::inlineScan()
|
||||
#endif
|
||||
memset(&iss, 0, sizeof(iss));
|
||||
iss.fd = this;
|
||||
if (fbody)
|
||||
if (fbody && !naked)
|
||||
{
|
||||
inlineNest++;
|
||||
fbody = fbody->inlineScan(&iss);
|
||||
@@ -1277,7 +1411,7 @@ void FuncDeclaration::inlineScan()
|
||||
}
|
||||
}
|
||||
|
||||
int FuncDeclaration::canInline(int hasthis, int hdrscan)
|
||||
int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
|
||||
{
|
||||
InlineCostState ics;
|
||||
int cost;
|
||||
@@ -1285,7 +1419,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)
|
||||
@@ -1299,7 +1433,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (inlineStatus)
|
||||
switch (statementsToo ? inlineStatusStmt : inlineStatusExp)
|
||||
{
|
||||
case ILSyes:
|
||||
#if CANINLINE_LOG
|
||||
@@ -1332,9 +1466,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;
|
||||
}
|
||||
@@ -1350,6 +1485,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
|
||||
|
||||
if (
|
||||
!fbody ||
|
||||
ident == Id::ensure || // ensure() has magic properties the inliner loses
|
||||
!hdrscan &&
|
||||
(
|
||||
#if 0
|
||||
@@ -1361,11 +1497,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())
|
||||
))
|
||||
@@ -1382,8 +1514,8 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
|
||||
{
|
||||
for (size_t i = 0; i < parameters->dim; i++)
|
||||
{
|
||||
VarDeclaration *v = (VarDeclaration *)parameters->data[i];
|
||||
if (/*v->isOut() || v->isRef() ||*/ v->type->toBasetype()->ty == Tsarray)
|
||||
VarDeclaration *v = parameters->tdata()[i];
|
||||
if (v->type->toBasetype()->ty == Tsarray)
|
||||
goto Lno;
|
||||
}
|
||||
}
|
||||
@@ -1396,18 +1528,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 (!hdrscan)
|
||||
{
|
||||
// Don't modify inlineStatus for header content scan
|
||||
if (statementsToo)
|
||||
inlineStatusStmt = ILSyes;
|
||||
else
|
||||
inlineStatusExp = ILSyes;
|
||||
|
||||
#if !IN_LLVM
|
||||
if (!hdrscan) // Don't scan recursively for header content scan
|
||||
inlineScan();
|
||||
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
|
||||
@@ -1415,26 +1576,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, Array *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;
|
||||
|
||||
if (ps)
|
||||
as = new Statements();
|
||||
|
||||
// Set up vthis
|
||||
if (ethis)
|
||||
{
|
||||
@@ -1490,6 +1659,8 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, A
|
||||
{
|
||||
e = new DeclarationExp(0, ids.vthis);
|
||||
e->type = Type::tvoid;
|
||||
if (as)
|
||||
as->push(new ExpStatement(e->loc, e));
|
||||
}
|
||||
|
||||
if (arguments && arguments->dim)
|
||||
@@ -1498,9 +1669,9 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, A
|
||||
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{
|
||||
VarDeclaration *vfrom = (VarDeclaration *)parameters->data[i];
|
||||
VarDeclaration *vfrom = parameters->tdata()[i];
|
||||
VarDeclaration *vto;
|
||||
Expression *arg = (Expression *)arguments->data[i];
|
||||
Expression *arg = arguments->tdata()[i];
|
||||
ExpInitializer *ei;
|
||||
VarExp *ve;
|
||||
|
||||
@@ -1530,18 +1701,31 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, A
|
||||
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'.
|
||||
@@ -1553,7 +1737,7 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, A
|
||||
* 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:
|
||||
@@ -1584,6 +1768,9 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, A
|
||||
//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;
|
||||
}
|
||||
|
||||
@@ -1603,7 +1790,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();
|
||||
|
||||
1070
dmd/interpret.c
1070
dmd/interpret.c
File diff suppressed because it is too large
Load Diff
35
dmd/lexer.c
35
dmd/lexer.c
@@ -123,11 +123,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
|
||||
@@ -1148,6 +1148,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;
|
||||
@@ -2073,7 +2079,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')
|
||||
{
|
||||
@@ -3016,6 +3028,7 @@ static Keyword keywords[] =
|
||||
{ "__thread", TOKtls },
|
||||
{ "__gshared", TOKgshared },
|
||||
{ "__traits", TOKtraits },
|
||||
{ "__vector", TOKvector },
|
||||
{ "__overloadset", TOKoverloadset },
|
||||
{ "__FILE__", TOKfile },
|
||||
{ "__LINE__", TOKline },
|
||||
@@ -3035,25 +3048,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(1543);
|
||||
|
||||
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);
|
||||
@@ -3150,6 +3160,7 @@ void Lexer::initKeywords()
|
||||
Token::tochars[TOKat] = "@";
|
||||
Token::tochars[TOKpow] = "^^";
|
||||
Token::tochars[TOKpowass] = "^^=";
|
||||
Token::tochars[TOKgoesto] = "=>";
|
||||
#endif
|
||||
|
||||
// For debugging
|
||||
|
||||
41
dmd/mars.c
41
dmd/mars.c
@@ -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
|
||||
@@ -72,9 +72,9 @@ Global::Global()
|
||||
obj_ext_alt = "obj";
|
||||
#endif
|
||||
|
||||
copyright = "Copyright (c) 1999-2011 by Digital Mars and Tomas Lindquist Olsen";
|
||||
copyright = "Copyright (c) 1999-2012 by Digital Mars and Tomas Lindquist Olsen";
|
||||
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
||||
version = "v1.072";
|
||||
version = "v1.073";
|
||||
ldc_version = "LDC trunk";
|
||||
llvm_version = "LLVM 3.0";
|
||||
global.structalign = 8;
|
||||
@@ -132,7 +132,7 @@ bool Loc::equals(const Loc& loc)
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Print error message and exit.
|
||||
* Print error message
|
||||
*/
|
||||
|
||||
void error(Loc loc, const char *format, ...)
|
||||
@@ -151,6 +151,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)
|
||||
@@ -174,6 +186,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)
|
||||
@@ -221,7 +252,7 @@ void fatal()
|
||||
void halt()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
*(char*)0=0;
|
||||
*(volatile char*)0=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -496,8 +496,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);
|
||||
#ifdef __GNUC__
|
||||
__attribute__((noreturn))
|
||||
#endif
|
||||
|
||||
20
dmd/module.c
20
dmd/module.c
@@ -726,6 +726,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.
|
||||
@@ -733,14 +739,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)
|
||||
|
||||
104
dmd/mtype.c
104
dmd/mtype.c
@@ -190,7 +190,7 @@ void Type::init(Ir* _sir)
|
||||
void Type::init()
|
||||
#endif
|
||||
{
|
||||
stringtable.init();
|
||||
stringtable.init(1543);
|
||||
deco_stringtable.init();
|
||||
Lexer::initKeywords();
|
||||
|
||||
@@ -1950,6 +1950,12 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
|
||||
*pe = (Expression *)o;
|
||||
return;
|
||||
}
|
||||
if (o->dyncast() == DYNCAST_TYPE)
|
||||
{
|
||||
*ps = NULL;
|
||||
*pt = (Type *)o;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a new TupleDeclaration which
|
||||
* is a slice [d..d+1] out of the old one.
|
||||
@@ -1992,7 +1998,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
||||
{ error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim);
|
||||
return Type::terror;
|
||||
}
|
||||
Object *o = (Object *)sd->objects->data[(size_t)d];
|
||||
Object *o = (*sd->objects)[(size_t)d];
|
||||
if (o->dyncast() != DYNCAST_TYPE)
|
||||
{ error(loc, "%s is not a type", toChars());
|
||||
return Type::terror;
|
||||
@@ -3154,6 +3160,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
|
||||
Scope *argsc = sc->push();
|
||||
argsc->stc = 0; // don't inherit storage class
|
||||
argsc->protection = PROTpublic;
|
||||
argsc->func = NULL;
|
||||
|
||||
size_t dim = Parameter::dim(tf->parameters);
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
@@ -4744,7 +4751,7 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
||||
if (!sym->members)
|
||||
{
|
||||
error(e->loc, "struct %s is forward referenced", sym->toChars());
|
||||
return new IntegerExp(e->loc, 0, Type::tint32);
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
/* If e.tupleof
|
||||
@@ -4755,10 +4762,11 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
||||
* (e.field0, e.field1, e.field2, ...)
|
||||
*/
|
||||
e = e->semantic(sc); // do this before turning on noaccesscheck
|
||||
e->type->size(); // do semantic of type
|
||||
Expressions *exps = new Expressions;
|
||||
exps->reserve(sym->fields.dim);
|
||||
for (size_t i = 0; i < sym->fields.dim; i++)
|
||||
{ VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
|
||||
{ VarDeclaration *v = sym->fields[i];
|
||||
Expression *fe = new DotVarExp(e->loc, e, v);
|
||||
exps->push(fe);
|
||||
}
|
||||
@@ -4820,9 +4828,8 @@ L1:
|
||||
|
||||
TemplateMixin *tm = s->isTemplateMixin();
|
||||
if (tm)
|
||||
{ Expression *de;
|
||||
|
||||
de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
|
||||
{
|
||||
Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
|
||||
de->type = e->type;
|
||||
return de;
|
||||
}
|
||||
@@ -4851,8 +4858,7 @@ L1:
|
||||
return de;
|
||||
}
|
||||
|
||||
Import *timp = s->isImport();
|
||||
if (timp)
|
||||
if (s->isImport() || s->isModule() || s->isPackage())
|
||||
{
|
||||
e = new DsymbolExp(e->loc, s);
|
||||
e = e->semantic(sc);
|
||||
@@ -4949,7 +4955,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
|
||||
structelems->setDim(sym->fields.dim);
|
||||
for (size_t j = 0; j < structelems->dim; j++)
|
||||
{
|
||||
VarDeclaration *vd = (VarDeclaration *)(sym->fields.data[j]);
|
||||
VarDeclaration *vd = sym->fields[j];
|
||||
Expression *e;
|
||||
if (vd->init)
|
||||
{ if (vd->init->isVoidInitializer())
|
||||
@@ -4959,7 +4965,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
|
||||
}
|
||||
else
|
||||
e = vd->type->defaultInitLiteral();
|
||||
structelems->data[j] = e;
|
||||
structelems->tdata()[j] = e;
|
||||
}
|
||||
StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
|
||||
// Why doesn't the StructLiteralExp constructor do this, when
|
||||
@@ -5020,6 +5026,7 @@ Type *TypeClass::semantic(Loc loc, Scope *sc)
|
||||
//printf("TypeClass::semantic(%s)\n", sym->toChars());
|
||||
if (deco)
|
||||
return this;
|
||||
//printf("\t%s\n", merge()->deco);
|
||||
return merge();
|
||||
}
|
||||
|
||||
@@ -5060,7 +5067,6 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
||||
VarDeclaration *v;
|
||||
Dsymbol *s;
|
||||
DotVarExp *de;
|
||||
Declaration *d;
|
||||
|
||||
#if LOGDOTEXP
|
||||
printf("TypeClass::dotExp(e='%s', ident='%s')\n", e->toChars(), ident->toChars());
|
||||
@@ -5084,10 +5090,11 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
||||
/* Create a TupleExp
|
||||
*/
|
||||
e = e->semantic(sc); // do this before turning on noaccesscheck
|
||||
e->type->size(); // do semantic of type
|
||||
Expressions *exps = new Expressions;
|
||||
exps->reserve(sym->fields.dim);
|
||||
for (size_t i = 0; i < sym->fields.dim; i++)
|
||||
{ VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
|
||||
{ VarDeclaration *v = sym->fields[i];
|
||||
// Don't include hidden 'this' pointer
|
||||
if (v->isThisDeclaration())
|
||||
continue;
|
||||
@@ -5107,22 +5114,16 @@ L1:
|
||||
if (!s)
|
||||
{
|
||||
// See if it's a base class
|
||||
ClassDeclaration *cbase;
|
||||
for (cbase = sym->baseClass; cbase; cbase = cbase->baseClass)
|
||||
if (Dsymbol *cbase = sym->searchBase(e->loc, ident))
|
||||
{
|
||||
if (cbase->ident->equals(ident))
|
||||
{
|
||||
e = new DotTypeExp(0, e, cbase);
|
||||
return e;
|
||||
}
|
||||
e = new DotTypeExp(0, e, cbase);
|
||||
return e;
|
||||
}
|
||||
|
||||
if (ident == Id::classinfo)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
assert(ClassDeclaration::classinfo);
|
||||
t = ClassDeclaration::classinfo->type;
|
||||
Type *t = ClassDeclaration::classinfo->type;
|
||||
if (e->op == TOKtype || e->op == TOKdottype)
|
||||
{
|
||||
/* For type.classinfo, we know the classinfo
|
||||
@@ -5271,9 +5272,8 @@ L1:
|
||||
|
||||
TemplateMixin *tm = s->isTemplateMixin();
|
||||
if (tm)
|
||||
{ Expression *de;
|
||||
|
||||
de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
|
||||
{
|
||||
Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
|
||||
de->type = e->type;
|
||||
return de;
|
||||
}
|
||||
@@ -5302,11 +5302,20 @@ L1:
|
||||
return de;
|
||||
}
|
||||
|
||||
d = s->isDeclaration();
|
||||
#if 0 // shouldn't this be here?
|
||||
if (s->isImport() || s->isModule() || s->isPackage())
|
||||
{
|
||||
e = new DsymbolExp(e->loc, s, 0);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
|
||||
Declaration *d = s->isDeclaration();
|
||||
if (!d)
|
||||
{
|
||||
e->error("%s.%s is not a declaration", e->toChars(), ident->toChars());
|
||||
return new IntegerExp(e->loc, 1, Type::tint32);
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
if (e->op == TOKtype)
|
||||
@@ -5335,7 +5344,7 @@ L1:
|
||||
{
|
||||
e = new ThisExp(e->loc);
|
||||
e = new DotTypeExp(e->loc, e, cd);
|
||||
de = new DotVarExp(e->loc, e, d);
|
||||
DotVarExp *de = new DotVarExp(e->loc, e, d);
|
||||
e = de->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
@@ -5345,7 +5354,10 @@ L1:
|
||||
}
|
||||
}
|
||||
|
||||
de = new DotVarExp(e->loc, new ThisExp(e->loc), d);
|
||||
/* Rewrite as:
|
||||
* this.d
|
||||
*/
|
||||
DotVarExp *de = new DotVarExp(e->loc, new ThisExp(e->loc), d);
|
||||
e = de->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
@@ -5371,9 +5383,7 @@ L1:
|
||||
if (d->parent && d->toParent()->isModule())
|
||||
{
|
||||
// (e, d)
|
||||
VarExp *ve;
|
||||
|
||||
ve = new VarExp(e->loc, d);
|
||||
VarExp *ve = new VarExp(e->loc, d);
|
||||
e = new CommaExp(e->loc, e, ve);
|
||||
e->type = d->type;
|
||||
return e;
|
||||
@@ -5413,7 +5423,7 @@ MATCH TypeClass::implicitConvTo(Type *to)
|
||||
|
||||
ClassDeclaration *cdto = to->isClassHandle();
|
||||
if (cdto && cdto->isBaseOf(sym, NULL))
|
||||
{ //printf("is base\n");
|
||||
{ //printf("'to' is base\n");
|
||||
return MATCHconvert;
|
||||
}
|
||||
|
||||
@@ -5745,19 +5755,18 @@ Parameters *Parameter::arraySyntaxCopy(Parameters *args)
|
||||
a = new Parameters();
|
||||
a->setDim(args->dim);
|
||||
for (size_t i = 0; i < a->dim; i++)
|
||||
{ Parameter *arg = (Parameter *)args->data[i];
|
||||
{ Parameter *arg = (*args)[i];
|
||||
|
||||
arg = arg->syntaxCopy();
|
||||
a->data[i] = (void *)arg;
|
||||
(*a)[i] = arg;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
char *Parameter::argsTypesToChars(Parameters *args, int varargs)
|
||||
{ OutBuffer *buf;
|
||||
|
||||
buf = new OutBuffer();
|
||||
{
|
||||
OutBuffer *buf = new OutBuffer();
|
||||
|
||||
buf->writeByte('(');
|
||||
if (args)
|
||||
@@ -5767,7 +5776,7 @@ char *Parameter::argsTypesToChars(Parameters *args, int varargs)
|
||||
for (size_t i = 0; i < args->dim; i++)
|
||||
{ if (i)
|
||||
buf->writeByte(',');
|
||||
Parameter *arg = (Parameter *)args->data[i];
|
||||
Parameter *arg = args->tdata()[i];
|
||||
argbuf.reset();
|
||||
arg->type->toCBuffer2(&argbuf, &hgs, 0);
|
||||
buf->write(&argbuf);
|
||||
@@ -5834,8 +5843,7 @@ void Parameter::argsToDecoBuffer(OutBuffer *buf, Parameters *arguments, bool man
|
||||
{
|
||||
//printf("Parameter::argsToDecoBuffer()\n");
|
||||
// Write argument types
|
||||
if (arguments)
|
||||
foreach(arguments, &argsToDecoBufferDg, buf, 0, mangle ? mangleFlag : 0);
|
||||
foreach(arguments, &argsToDecoBufferDg, buf);
|
||||
}
|
||||
|
||||
/****************************************
|
||||
@@ -5853,9 +5861,7 @@ static int isTPLDg(void *ctx, size_t n, Parameter *arg, int)
|
||||
int Parameter::isTPL(Parameters *arguments)
|
||||
{
|
||||
//printf("Parameter::isTPL()\n");
|
||||
if (arguments)
|
||||
return foreach(arguments, &isTPLDg, NULL);
|
||||
return 0;
|
||||
return foreach(arguments, &isTPLDg, NULL);
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
@@ -5904,6 +5910,7 @@ void Parameter::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||
break;
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("storageClass = x%llx\n", storageClass & (STCin | STCout | STCref | STClazy));
|
||||
halt();
|
||||
#endif
|
||||
assert(0);
|
||||
@@ -5924,8 +5931,7 @@ static int dimDg(void *ctx, size_t n, Parameter *, int)
|
||||
size_t Parameter::dim(Parameters *args)
|
||||
{
|
||||
size_t n = 0;
|
||||
if (args)
|
||||
foreach(args, &dimDg, &n);
|
||||
foreach(args, &dimDg, &n);
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -5970,7 +5976,9 @@ Parameter *Parameter::getNth(Parameters *args, size_t nth, size_t *pn)
|
||||
|
||||
int Parameter::foreach(Parameters *args, Parameter::ForeachDg dg, void *ctx, size_t *pn, int flags)
|
||||
{
|
||||
assert(args && dg);
|
||||
assert(dg);
|
||||
if (!args)
|
||||
return 0;
|
||||
|
||||
size_t n = pn ? *pn : 0; // take over index
|
||||
int result = 0;
|
||||
|
||||
@@ -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
|
||||
@@ -122,11 +122,11 @@ Expression *StructLiteralExp::optimize(int result)
|
||||
if (elements)
|
||||
{
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = (Expression *)elements->data[i];
|
||||
{ Expression *e = (*elements)[i];
|
||||
if (!e)
|
||||
continue;
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
elements->data[i] = (void *)e;
|
||||
(*elements)[i] = e;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@@ -329,20 +329,20 @@ Expression *NewExp::optimize(int result)
|
||||
if (newargs)
|
||||
{
|
||||
for (size_t i = 0; i < newargs->dim; i++)
|
||||
{ Expression *e = (Expression *)newargs->data[i];
|
||||
{ Expression *e = newargs->tdata()[i];
|
||||
|
||||
e = e->optimize(WANTvalue);
|
||||
newargs->data[i] = (void *)e;
|
||||
newargs->tdata()[i] = e;
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments)
|
||||
{
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *e = (Expression *)arguments->data[i];
|
||||
{ Expression *e = arguments->tdata()[i];
|
||||
|
||||
e = e->optimize(WANTvalue);
|
||||
arguments->data[i] = (void *)e;
|
||||
arguments->tdata()[i] = e;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@@ -357,10 +357,10 @@ Expression *CallExp::optimize(int result)
|
||||
if (arguments)
|
||||
{
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *e = (Expression *)arguments->data[i];
|
||||
{ Expression *e = arguments->tdata()[i];
|
||||
|
||||
e = e->optimize(WANTvalue);
|
||||
arguments->data[i] = (void *)e;
|
||||
arguments->tdata()[i] = e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,8 +466,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);
|
||||
}
|
||||
}
|
||||
@@ -561,8 +561,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)
|
||||
@@ -641,13 +641,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)
|
||||
@@ -784,8 +781,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
|
||||
@@ -802,7 +803,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;
|
||||
@@ -833,7 +838,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;
|
||||
|
||||
57
dmd/parse.c
57
dmd/parse.c
@@ -1301,36 +1301,49 @@ Dsymbol *Parser::parseAggregate()
|
||||
|
||||
BaseClasses *Parser::parseBaseClasses()
|
||||
{
|
||||
enum PROT protection = PROTpublic;
|
||||
BaseClasses *baseclasses = new BaseClasses();
|
||||
|
||||
for (; 1; nextToken())
|
||||
{
|
||||
bool prot = false;
|
||||
enum PROT protection = PROTpublic;
|
||||
switch (token.value)
|
||||
{
|
||||
case TOKidentifier:
|
||||
break;
|
||||
case TOKprivate:
|
||||
prot = true;
|
||||
protection = PROTprivate;
|
||||
continue;
|
||||
nextToken();
|
||||
break;
|
||||
case TOKpackage:
|
||||
prot = true;
|
||||
protection = PROTpackage;
|
||||
continue;
|
||||
nextToken();
|
||||
break;
|
||||
case TOKprotected:
|
||||
prot = true;
|
||||
protection = PROTprotected;
|
||||
continue;
|
||||
nextToken();
|
||||
break;
|
||||
case TOKpublic:
|
||||
prot = true;
|
||||
protection = PROTpublic;
|
||||
continue;
|
||||
default:
|
||||
error("base classes expected instead of %s", token.toChars());
|
||||
return NULL;
|
||||
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);
|
||||
baseclasses->push(b);
|
||||
if (token.value != TOKcomma)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
error("base classes expected instead of %s", token.toChars());
|
||||
return NULL;
|
||||
}
|
||||
BaseClass *b = new BaseClass(parseBasicType(), protection);
|
||||
baseclasses->push(b);
|
||||
if (token.value != TOKcomma)
|
||||
break;
|
||||
protection = PROTpublic;
|
||||
}
|
||||
return baseclasses;
|
||||
}
|
||||
@@ -3493,7 +3506,7 @@ Statement *Parser::parseStatement(int flags)
|
||||
|
||||
case TOKtry:
|
||||
{ Statement *body;
|
||||
Array *catches = NULL;
|
||||
Catches *catches = NULL;
|
||||
Statement *finalbody = NULL;
|
||||
|
||||
nextToken();
|
||||
@@ -3523,7 +3536,7 @@ Statement *Parser::parseStatement(int flags)
|
||||
handler = parseStatement(0);
|
||||
c = new Catch(loc, t, id, handler);
|
||||
if (!catches)
|
||||
catches = new Array();
|
||||
catches = new Catches();
|
||||
catches->push(c);
|
||||
}
|
||||
|
||||
@@ -3962,9 +3975,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;
|
||||
@@ -4731,9 +4747,8 @@ Expression *Parser::parsePostExp(Expression *e)
|
||||
{
|
||||
nextToken();
|
||||
while (1)
|
||||
{ Expression *arg;
|
||||
|
||||
arg = parseAssignExp();
|
||||
{
|
||||
Expression *arg = parseAssignExp();
|
||||
arguments->push(arg);
|
||||
if (token.value == TOKrbracket)
|
||||
break;
|
||||
@@ -5369,7 +5384,7 @@ Expressions *Parser::parseArguments()
|
||||
nextToken();
|
||||
if (token.value != endtok)
|
||||
{
|
||||
while (1)
|
||||
while (token.value != TOKeof)
|
||||
{
|
||||
arg = parseAssignExp();
|
||||
arguments->push(arg);
|
||||
|
||||
@@ -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.
|
||||
|
||||
34
dmd/sideeffect.c
Normal file
34
dmd/sideeffect.c
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
// 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"
|
||||
|
||||
/********************************************
|
||||
* Determine if Expression has any side effects.
|
||||
*/
|
||||
|
||||
bool Expression::hasSideEffect()
|
||||
{
|
||||
return checkSideEffect(2);
|
||||
}
|
||||
|
||||
176
dmd/statement.c
176
dmd/statement.c
@@ -327,9 +327,8 @@ void ExpStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexcepti
|
||||
DeclarationExp *de = (DeclarationExp *)(exp);
|
||||
VarDeclaration *v = de->declaration->isVarDeclaration();
|
||||
if (v)
|
||||
{ Expression *e;
|
||||
|
||||
e = v->callScopeDtor(sc);
|
||||
{
|
||||
Expression *e = v->callScopeDtor(sc);
|
||||
if (e)
|
||||
{
|
||||
//printf("dtor is: "); e->print();
|
||||
@@ -451,7 +450,7 @@ Statement *CompoundStatement::syntaxCopy()
|
||||
Statements *a = new Statements();
|
||||
a->setDim(statements->dim);
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *)statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s)
|
||||
s = s->syntaxCopy();
|
||||
a->data[i] = s;
|
||||
@@ -468,7 +467,7 @@ Statement *CompoundStatement::semantic(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < statements->dim; )
|
||||
{
|
||||
s = (Statement *) statements->data[i];
|
||||
s = (*statements)[i];
|
||||
if (s)
|
||||
{ Statements *a = s->flatten(sc);
|
||||
|
||||
@@ -479,7 +478,7 @@ Statement *CompoundStatement::semantic(Scope *sc)
|
||||
continue;
|
||||
}
|
||||
s = s->semantic(sc);
|
||||
statements->data[i] = s;
|
||||
(*statements)[i] = s;
|
||||
if (s)
|
||||
{
|
||||
Statement *sentry;
|
||||
@@ -493,17 +492,11 @@ Statement *CompoundStatement::semantic(Scope *sc)
|
||||
statements->data[i] = sentry;
|
||||
}
|
||||
if (sexception)
|
||||
sexception = sexception->semantic(sc);
|
||||
if (sexception)
|
||||
{
|
||||
if (i + 1 == statements->dim && !sfinally)
|
||||
{
|
||||
#if 1
|
||||
sexception = sexception->semantic(sc);
|
||||
#else
|
||||
statements->push(sexception);
|
||||
if (sfinally)
|
||||
// Assume sexception does not throw
|
||||
statements->push(sfinally);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -515,22 +508,23 @@ Statement *CompoundStatement::semantic(Scope *sc)
|
||||
* catch (Object __o)
|
||||
* { sexception; throw __o; }
|
||||
*/
|
||||
Statement *body;
|
||||
Statements *a = new Statements();
|
||||
|
||||
for (size_t j = i + 1; j < statements->dim; j++)
|
||||
{
|
||||
a->push((*statements)[j]);
|
||||
}
|
||||
body = new CompoundStatement(0, a);
|
||||
Statement *body = new CompoundStatement(0, a);
|
||||
body = new ScopeStatement(0, body);
|
||||
|
||||
Identifier *id = Lexer::uniqueId("__o");
|
||||
|
||||
Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
|
||||
handler = new CompoundStatement(0, sexception, handler);
|
||||
Statement *handler = sexception;
|
||||
if (sexception->blockExit(FALSE) & BEfallthru)
|
||||
{ handler = new ThrowStatement(0, new IdentifierExp(0, id));
|
||||
handler = new CompoundStatement(0, sexception, handler);
|
||||
}
|
||||
|
||||
Array *catches = new Array();
|
||||
Catches *catches = new Catches();
|
||||
Catch *ctch = new Catch(0, NULL, id, handler);
|
||||
catches->push(ctch);
|
||||
s = new TryCatchStatement(0, body, catches);
|
||||
@@ -556,14 +550,12 @@ Statement *CompoundStatement::semantic(Scope *sc)
|
||||
* As:
|
||||
* s; try { s1; s2; } finally { sfinally; }
|
||||
*/
|
||||
Statement *body;
|
||||
Statements *a = new Statements();
|
||||
|
||||
for (size_t j = i + 1; j < statements->dim; j++)
|
||||
{
|
||||
a->push((*statements)[j]);
|
||||
}
|
||||
body = new CompoundStatement(0, a);
|
||||
Statement *body = new CompoundStatement(0, a);
|
||||
s = new TryFinallyStatement(0, body, sfinally);
|
||||
s = s->semantic(sc);
|
||||
statements->setDim(i + 1);
|
||||
@@ -606,7 +598,7 @@ ReturnStatement *CompoundStatement::isReturnStatement()
|
||||
void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s)
|
||||
s->toCBuffer(buf, hgs);
|
||||
}
|
||||
@@ -615,7 +607,7 @@ void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
int CompoundStatement::usesEH()
|
||||
{
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s && s->usesEH())
|
||||
return TRUE;
|
||||
}
|
||||
@@ -627,7 +619,7 @@ int CompoundStatement::blockExit(bool mustNotThrow)
|
||||
//printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
|
||||
int result = BEfallthru;
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s)
|
||||
{
|
||||
//printf("result = x%x\n", result);
|
||||
@@ -652,7 +644,7 @@ int CompoundStatement::comeFrom()
|
||||
|
||||
//printf("CompoundStatement::comeFrom()\n");
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *)statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
|
||||
if (!s)
|
||||
continue;
|
||||
@@ -665,7 +657,7 @@ int CompoundStatement::comeFrom()
|
||||
int CompoundStatement::isEmpty()
|
||||
{
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s && !s->isEmpty())
|
||||
return FALSE;
|
||||
}
|
||||
@@ -686,7 +678,7 @@ Statement *CompoundDeclarationStatement::syntaxCopy()
|
||||
Statements *a = new Statements();
|
||||
a->setDim(statements->dim);
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *)statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s)
|
||||
s = s->syntaxCopy();
|
||||
a->data[i] = s;
|
||||
@@ -699,7 +691,7 @@ void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
int nwritten = 0;
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
ExpStatement *ds;
|
||||
if (s &&
|
||||
(ds = s->isExpStatement()) != NULL &&
|
||||
@@ -764,7 +756,7 @@ Statement *UnrolledLoopStatement::syntaxCopy()
|
||||
Statements *a = new Statements();
|
||||
a->setDim(statements->dim);
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *)statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s)
|
||||
s = s->syntaxCopy();
|
||||
a->data[i] = s;
|
||||
@@ -785,7 +777,7 @@ Statement *UnrolledLoopStatement::semantic(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{
|
||||
Statement *s = (Statement *) statements->data[i];
|
||||
Statement *s = (*statements)[i];
|
||||
if (s)
|
||||
{
|
||||
//printf("[%d]: %s\n", i, s->toChars());
|
||||
@@ -807,7 +799,7 @@ void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s;
|
||||
|
||||
s = (Statement *) statements->data[i];
|
||||
s = (*statements)[i];
|
||||
if (s)
|
||||
s->toCBuffer(buf, hgs);
|
||||
}
|
||||
@@ -829,7 +821,7 @@ int UnrolledLoopStatement::hasContinue()
|
||||
int UnrolledLoopStatement::usesEH()
|
||||
{
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s && s->usesEH())
|
||||
return TRUE;
|
||||
}
|
||||
@@ -840,7 +832,7 @@ int UnrolledLoopStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
int result = BEfallthru;
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
if (s)
|
||||
{
|
||||
int r = s->blockExit(mustNotThrow);
|
||||
@@ -856,7 +848,7 @@ int UnrolledLoopStatement::comeFrom()
|
||||
|
||||
//printf("UnrolledLoopStatement::comeFrom()\n");
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *)statements->data[i];
|
||||
{ Statement *s = (*statements)[i];
|
||||
|
||||
if (!s)
|
||||
continue;
|
||||
@@ -1360,6 +1352,8 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
error("invalid foreach aggregate %s", aggr->toChars());
|
||||
return this;
|
||||
}
|
||||
if (aggr->type->toBasetype()->ty == Terror)
|
||||
return NULL;
|
||||
|
||||
inferApplyArgTypes(op, arguments, aggr, sc->module);
|
||||
|
||||
@@ -1402,10 +1396,10 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
Expression *e;
|
||||
Type *t;
|
||||
if (te)
|
||||
e = te->exps->tdata()[k];
|
||||
e = (*te->exps)[k];
|
||||
else
|
||||
t = Parameter::getNth(tuple->arguments, k)->type;
|
||||
Parameter *arg = arguments->tdata()[0];
|
||||
Parameter *arg = (*arguments)[0];
|
||||
Statements *st = new Statements();
|
||||
|
||||
if (dim == 2)
|
||||
@@ -1508,7 +1502,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
{ Parameter *arg;
|
||||
|
||||
int i = (dim == 1) ? 0 : 1; // index of value
|
||||
arg = (Parameter *)arguments->data[i];
|
||||
arg = (*arguments)[i];
|
||||
arg->type = arg->type->semantic(loc, sc);
|
||||
tnv = arg->type->toBasetype();
|
||||
if (tnv->ty != tn->ty &&
|
||||
@@ -1517,7 +1511,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
if (arg->storageClass & STCref)
|
||||
error("foreach: value of UTF conversion cannot be ref");
|
||||
if (dim == 2)
|
||||
{ arg = (Parameter *)arguments->data[0];
|
||||
{ arg = (*arguments)[0];
|
||||
if (arg->storageClass & STCref)
|
||||
error("foreach: key cannot be ref");
|
||||
}
|
||||
@@ -1527,7 +1521,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ // Declare args
|
||||
Parameter *arg = (Parameter *)arguments->data[i];
|
||||
Parameter *arg = (*arguments)[i];
|
||||
Type *argtype = arg->type->semantic(loc, sc);
|
||||
VarDeclaration *var;
|
||||
|
||||
@@ -1705,7 +1699,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
e = new VarExp(loc, r);
|
||||
Expression *einit = new DotIdExp(loc, e, idhead);
|
||||
// einit = einit->semantic(sc);
|
||||
Parameter *arg = (Parameter *)arguments->data[0];
|
||||
Parameter *arg = (*arguments)[0];
|
||||
VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
|
||||
ve->storage_class |= STCforeach;
|
||||
ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
|
||||
@@ -1755,7 +1749,8 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
*/
|
||||
Parameters *args = new Parameters();
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ Parameter *arg = (Parameter *)arguments->data[i];
|
||||
{ Parameter *arg = (*arguments)[i];
|
||||
StorageClass stc = STCref;
|
||||
Identifier *id;
|
||||
|
||||
arg->type = arg->type->semantic(loc, sc);
|
||||
@@ -1776,7 +1771,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
}
|
||||
Type *t = new TypeFunction(args, Type::tint32, 0, LINKd);
|
||||
cases = new Statements();
|
||||
gotos = new Array();
|
||||
gotos = new CompoundStatements();
|
||||
FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
|
||||
fld->fbody = body;
|
||||
Expression *flde = new FuncExp(loc, fld);
|
||||
@@ -1784,28 +1779,28 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
|
||||
// Resolve any forward referenced goto's
|
||||
for (size_t i = 0; i < gotos->dim; i++)
|
||||
{ CompoundStatement *cs = (CompoundStatement *)gotos->data[i];
|
||||
GotoStatement *gs = (GotoStatement *)cs->statements->data[0];
|
||||
{ CompoundStatement *cs = (*gotos)[i];
|
||||
GotoStatement *gs = (GotoStatement *)(*cs->statements)[0];
|
||||
|
||||
if (!gs->label->statement)
|
||||
{ // 'Promote' it to this scope, and replace with a return
|
||||
cases->push(gs);
|
||||
s = new ReturnStatement(0, new IntegerExp(cases->dim + 1));
|
||||
cs->statements->data[0] = (void *)s;
|
||||
(*cs->statements)[0] = s;
|
||||
}
|
||||
}
|
||||
|
||||
if (taa)
|
||||
{
|
||||
// Check types
|
||||
Parameter *arg = (Parameter *)arguments->data[0];
|
||||
Parameter *arg = (*arguments)[0];
|
||||
if (dim == 2)
|
||||
{
|
||||
if (arg->storageClass & STCref)
|
||||
error("foreach: index cannot be ref");
|
||||
if (!arg->type->equals(taa->index))
|
||||
error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars());
|
||||
arg = (Parameter *)arguments->data[1];
|
||||
arg = (*arguments)[1];
|
||||
}
|
||||
if (!arg->type->equals(taa->nextOf()))
|
||||
error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars());
|
||||
@@ -1985,7 +1980,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
// cases 2...
|
||||
for (size_t i = 0; i < cases->dim; i++)
|
||||
{
|
||||
s = (Statement *)cases->data[i];
|
||||
s = (*cases)[i];
|
||||
s = new CaseStatement(0, new IntegerExp(i + 2), s);
|
||||
a->push(s);
|
||||
}
|
||||
@@ -2052,7 +2047,7 @@ void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writestring(" (");
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{
|
||||
Parameter *a = (Parameter *)arguments->data[i];
|
||||
Parameter *a = (*arguments)[i];
|
||||
if (i)
|
||||
buf->writestring(", ");
|
||||
if (a->storageClass & STCref)
|
||||
@@ -2553,7 +2548,7 @@ Statement *PragmaStatement::semantic(Scope *sc)
|
||||
{
|
||||
for (size_t i = 0; i < args->dim; i++)
|
||||
{
|
||||
Expression *e = args->tdata()[i];
|
||||
Expression *e = (*args)[i];
|
||||
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
@@ -2579,11 +2574,11 @@ Statement *PragmaStatement::semantic(Scope *sc)
|
||||
error("string expected for library name");
|
||||
else
|
||||
{
|
||||
Expression *e = args->tdata()[0];
|
||||
Expression *e = (*args)[0];
|
||||
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
args->tdata()[0] = e;
|
||||
(*args)[0] = e;
|
||||
StringExp *se = e->toString();
|
||||
if (!se)
|
||||
error("string expected for library name, not '%s'", e->toChars());
|
||||
@@ -2611,10 +2606,10 @@ Statement *PragmaStatement::semantic(Scope *sc)
|
||||
error("function name expected for start address");
|
||||
else
|
||||
{
|
||||
Expression *e = (Expression *)args->data[0];
|
||||
Expression *e = (*args)[0];
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
args->data[0] = (void *)e;
|
||||
(*args)[0] = e;
|
||||
Dsymbol *sa = getDsymbol(e);
|
||||
if (!sa || !sa->isFuncDeclaration())
|
||||
error("function name expected for start address, not '%s'", e->toChars());
|
||||
@@ -2771,7 +2766,7 @@ Statement *SwitchStatement::semantic(Scope *sc)
|
||||
// Resolve any goto case's with exp
|
||||
for (size_t i = 0; i < gotoCases.dim; i++)
|
||||
{
|
||||
GotoCaseStatement *gcs = (GotoCaseStatement *)gotoCases.data[i];
|
||||
GotoCaseStatement *gcs = gotoCases[i];
|
||||
|
||||
if (!gcs->exp)
|
||||
{
|
||||
@@ -2785,7 +2780,7 @@ Statement *SwitchStatement::semantic(Scope *sc)
|
||||
continue;
|
||||
for (size_t j = 0; j < scx->sw->cases->dim; j++)
|
||||
{
|
||||
CaseStatement *cs = (CaseStatement *)scx->sw->cases->data[j];
|
||||
CaseStatement *cs = (*scx->sw->cases)[j];
|
||||
|
||||
if (cs->exp->equals(gcs->exp))
|
||||
{
|
||||
@@ -2845,11 +2840,11 @@ Statement *SwitchStatement::semantic(Scope *sc)
|
||||
size_t dim = ed->members->dim;
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{
|
||||
EnumMember *em = ((Dsymbol *)ed->members->data[i])->isEnumMember();
|
||||
EnumMember *em = (*ed->members)[i]->isEnumMember();
|
||||
if (em)
|
||||
{
|
||||
for (size_t j = 0; j < cases->dim; j++)
|
||||
{ CaseStatement *cs = (CaseStatement *)cases->data[j];
|
||||
{ CaseStatement *cs = (*cases)[j];
|
||||
if (cs->exp->equals(em->value))
|
||||
goto L1;
|
||||
}
|
||||
@@ -2962,7 +2957,7 @@ Statement *CaseStatement::semantic(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < sw->cases->dim; i++)
|
||||
{
|
||||
CaseStatement *cs = (CaseStatement *)sw->cases->data[i];
|
||||
CaseStatement *cs = (*sw->cases)[i];
|
||||
|
||||
//printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
|
||||
if (cs->exp->equals(exp))
|
||||
@@ -2976,7 +2971,7 @@ Statement *CaseStatement::semantic(Scope *sc)
|
||||
// Resolve any goto case's with no exp to this case statement
|
||||
for (size_t i = 0; i < sw->gotoCases.dim; i++)
|
||||
{
|
||||
GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i];
|
||||
GotoCaseStatement *gcs = sw->gotoCases[i];
|
||||
|
||||
if (!gcs->exp)
|
||||
{
|
||||
@@ -3304,19 +3299,10 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
||||
FuncDeclaration *fd = sc->parent->isFuncDeclaration();
|
||||
Scope *scx = sc;
|
||||
int implicit0 = 0;
|
||||
Expression *eorg = NULL;
|
||||
|
||||
if (sc->fes)
|
||||
{
|
||||
// Find scope of function foreach is in
|
||||
for (; 1; scx = scx->enclosing)
|
||||
{
|
||||
assert(scx);
|
||||
if (scx->func != fd)
|
||||
{ fd = scx->func; // fd is now function enclosing foreach
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fd->fes)
|
||||
fd = fd->fes->func; // fd is now function enclosing foreach
|
||||
|
||||
Type *tret = fd->type->nextOf();
|
||||
if (fd->tintro)
|
||||
@@ -3379,10 +3365,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
||||
else
|
||||
fd->nrvo_can = 0;
|
||||
|
||||
if (fd->returnLabel && tbret->ty != Tvoid)
|
||||
{
|
||||
}
|
||||
else if (fd->inferRetType)
|
||||
if (fd->inferRetType)
|
||||
{
|
||||
Type *tfret = fd->type->nextOf();
|
||||
if (tfret)
|
||||
@@ -3400,11 +3383,17 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
||||
tbret = tret->toBasetype();
|
||||
}
|
||||
}
|
||||
if (fd->returnLabel)
|
||||
eorg = exp;
|
||||
}
|
||||
else if (tbret->ty != Tvoid)
|
||||
{
|
||||
if (fd->tintro)
|
||||
exp = exp->implicitCastTo(sc, fd->type->nextOf());
|
||||
|
||||
// eorg isn't casted to tret (== fd->tintro->nextOf())
|
||||
if (fd->returnLabel)
|
||||
eorg = exp->copy();
|
||||
exp = exp->implicitCastTo(sc, tret);
|
||||
}
|
||||
}
|
||||
@@ -3419,7 +3408,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
||||
else
|
||||
{
|
||||
fd->type->next = Type::tvoid;
|
||||
fd->type = fd->type->semantic(loc, sc);
|
||||
//fd->type = fd->type->semantic(loc, sc);
|
||||
if (!fd->tintro)
|
||||
{ tret = Type::tvoid;
|
||||
tbret = tret;
|
||||
@@ -3490,7 +3479,8 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
||||
assert(fd->vresult);
|
||||
VarExp *v = new VarExp(0, fd->vresult);
|
||||
|
||||
exp = new AssignExp(loc, v, exp);
|
||||
assert(eorg);
|
||||
exp = new AssignExp(loc, v, eorg);
|
||||
exp->op = TOKconstruct;
|
||||
exp = exp->semantic(sc);
|
||||
}
|
||||
@@ -4027,7 +4017,7 @@ int WithStatement::blockExit(bool mustNotThrow)
|
||||
|
||||
/******************************** TryCatchStatement ***************************/
|
||||
|
||||
TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches)
|
||||
TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Catches *catches)
|
||||
: Statement(loc)
|
||||
{
|
||||
this->body = body;
|
||||
@@ -4036,14 +4026,14 @@ TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches)
|
||||
|
||||
Statement *TryCatchStatement::syntaxCopy()
|
||||
{
|
||||
Array *a = new Array();
|
||||
Catches *a = new Catches();
|
||||
a->setDim(catches->dim);
|
||||
for (size_t i = 0; i < a->dim; i++)
|
||||
{ Catch *c;
|
||||
|
||||
c = (Catch *)catches->data[i];
|
||||
c = (*catches)[i];
|
||||
c = c->syntaxCopy();
|
||||
a->data[i] = c;
|
||||
(*a)[i] = c;
|
||||
}
|
||||
TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a);
|
||||
return s;
|
||||
@@ -4056,12 +4046,12 @@ Statement *TryCatchStatement::semantic(Scope *sc)
|
||||
/* Even if body is NULL, still do semantic analysis on catches
|
||||
*/
|
||||
for (size_t i = 0; i < catches->dim; i++)
|
||||
{ Catch *c = (Catch *)catches->data[i];
|
||||
{ Catch *c = (*catches)[i];
|
||||
c->semantic(sc);
|
||||
|
||||
// Determine if current catch 'hides' any previous catches
|
||||
for (size_t j = 0; j < i; j++)
|
||||
{ Catch *cj = (Catch *)catches->data[j];
|
||||
{ Catch *cj = (*catches)[j];
|
||||
char *si = c->loc.toChars();
|
||||
char *sj = cj->loc.toChars();
|
||||
|
||||
@@ -4095,7 +4085,7 @@ int TryCatchStatement::blockExit(bool mustNotThrow)
|
||||
int catchresult = 0;
|
||||
for (size_t i = 0; i < catches->dim; i++)
|
||||
{
|
||||
Catch *c = (Catch *)catches->data[i];
|
||||
Catch *c =(* catches)[i];
|
||||
if (c->type == Type::terror)
|
||||
continue;
|
||||
|
||||
@@ -4125,7 +4115,7 @@ void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
body->toCBuffer(buf, hgs);
|
||||
for (size_t i = 0; i < catches->dim; i++)
|
||||
{
|
||||
Catch *c = (Catch *)catches->data[i];
|
||||
Catch *c = (*catches)[i];
|
||||
c->toCBuffer(buf, hgs);
|
||||
}
|
||||
}
|
||||
@@ -4448,10 +4438,10 @@ Statements *VolatileStatement::flatten(Scope *sc)
|
||||
a = statement ? statement->flatten(sc) : NULL;
|
||||
if (a)
|
||||
{ for (size_t i = 0; i < a->dim; i++)
|
||||
{ Statement *s = (Statement *)a->data[i];
|
||||
{ Statement *s = (*a)[i];
|
||||
|
||||
s = new VolatileStatement(loc, s);
|
||||
a->data[i] = s;
|
||||
(*a)[i] = s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4511,7 +4501,7 @@ Statement *GotoStatement::semantic(Scope *sc)
|
||||
* list.
|
||||
*/
|
||||
Statements *a = new Statements();
|
||||
Statement *s;
|
||||
CompoundStatement *s;
|
||||
|
||||
a->push(this);
|
||||
s = new CompoundStatement(loc, a);
|
||||
@@ -4599,10 +4589,10 @@ Statements *LabelStatement::flatten(Scope *sc)
|
||||
{
|
||||
a->push(new ExpStatement(loc, (Expression *)NULL));
|
||||
}
|
||||
Statement *s = (Statement *)a->data[0];
|
||||
Statement *s = (*a)[0];
|
||||
|
||||
s = new LabelStatement(loc, ident, s);
|
||||
a->data[0] = s;
|
||||
(*a)[0] = s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +132,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
|
||||
@@ -176,6 +177,7 @@ struct ExpStatement : Statement
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Statement *doInlineStatement(InlineDoState *ids);
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -218,6 +220,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);
|
||||
@@ -256,6 +259,7 @@ struct UnrolledLoopStatement : Statement
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Statement *doInlineStatement(InlineDoState *ids);
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -278,6 +282,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);
|
||||
@@ -344,7 +351,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);
|
||||
};
|
||||
@@ -362,7 +371,7 @@ struct ForeachStatement : Statement
|
||||
FuncDeclaration *func; // function we're lexically in
|
||||
|
||||
Statements *cases; // put breaks, continues, gotos and returns here
|
||||
Array *gotos; // forward referenced goto's go here
|
||||
CompoundStatements *gotos; // forward referenced goto's go here
|
||||
|
||||
ForeachStatement(Loc loc, enum TOK op, Parameters *arguments, Expression *aggr, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
@@ -430,6 +439,7 @@ struct IfStatement : Statement
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Statement *doInlineStatement(InlineDoState *ids);
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -485,8 +495,8 @@ struct SwitchStatement : Statement
|
||||
|
||||
DefaultStatement *sdefault;
|
||||
|
||||
Array gotoCases; // array of unresolved GotoCaseStatement's
|
||||
CaseStatements *cases; // array of CaseStatement's
|
||||
GotoCaseStatements gotoCases; // array of unresolved GotoCaseStatement's
|
||||
CaseStatements *cases; // array of CaseStatement's
|
||||
int hasNoDefault; // !=0 if no default statement
|
||||
|
||||
// LDC
|
||||
@@ -634,6 +644,7 @@ struct ReturnStatement : Statement
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Statement *doInlineStatement(InlineDoState *ids);
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -720,9 +731,9 @@ struct WithStatement : Statement
|
||||
struct TryCatchStatement : Statement
|
||||
{
|
||||
Statement *body;
|
||||
Array *catches;
|
||||
Catches *catches;
|
||||
|
||||
TryCatchStatement(Loc loc, Statement *body, Array *catches);
|
||||
TryCatchStatement(Loc loc, Statement *body, Catches *catches);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
@@ -847,7 +858,7 @@ struct LabelStatement : Statement
|
||||
Statement* enclosingScopeExit;
|
||||
block *lblock; // back end
|
||||
|
||||
Array *fwdrefs; // forward references to this LabelStatement
|
||||
Blocks *fwdrefs; // forward references to this LabelStatement
|
||||
|
||||
LabelStatement(Loc loc, Identifier *ident, Statement *statement);
|
||||
Statement *syntaxCopy();
|
||||
@@ -882,8 +893,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 (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();
|
||||
|
||||
@@ -54,10 +54,15 @@ void StaticAssert::semantic2(Scope *sc)
|
||||
{
|
||||
//printf("StaticAssert::semantic2() %s\n", toChars());
|
||||
Expression *e = exp->semantic(sc);
|
||||
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;
|
||||
|
||||
28
dmd/struct.c
28
dmd/struct.c
@@ -54,6 +54,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
aliasthis = NULL;
|
||||
noDefaultCtor = FALSE;
|
||||
#endif
|
||||
dtor = NULL;
|
||||
|
||||
#if IN_LLVM
|
||||
availableExternally = true; // assume this unless proven otherwise
|
||||
@@ -77,7 +78,7 @@ void AggregateDeclaration::semantic2(Scope *sc)
|
||||
sc = sc->push(this);
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
s->semantic2(sc);
|
||||
}
|
||||
sc->pop();
|
||||
@@ -96,7 +97,7 @@ void AggregateDeclaration::semantic3(Scope *sc)
|
||||
sc = sc->push(this);
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
s->semantic3(sc);
|
||||
}
|
||||
sc->pop();
|
||||
@@ -110,7 +111,7 @@ void AggregateDeclaration::inlineScan()
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
//printf("inline scan aggregate symbol '%s'\n", s->toChars());
|
||||
s->inlineScan();
|
||||
}
|
||||
@@ -141,6 +142,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.
|
||||
@@ -238,13 +244,13 @@ int AggregateDeclaration::firstFieldInUnion(int indx)
|
||||
{
|
||||
if (isUnionDeclaration())
|
||||
return 0;
|
||||
VarDeclaration * vd = (VarDeclaration *)fields.data[indx];
|
||||
VarDeclaration * vd = fields.tdata()[indx];
|
||||
int firstNonZero = indx; // first index in the union with non-zero size
|
||||
for (; ;)
|
||||
{
|
||||
if (indx == 0)
|
||||
return firstNonZero;
|
||||
VarDeclaration * v = (VarDeclaration *)fields.data[indx - 1];
|
||||
VarDeclaration * v = fields.tdata()[indx - 1];
|
||||
if (v->offset != vd->offset)
|
||||
return firstNonZero;
|
||||
--indx;
|
||||
@@ -263,7 +269,7 @@ int AggregateDeclaration::firstFieldInUnion(int indx)
|
||||
*/
|
||||
int AggregateDeclaration::numFieldsInUnion(int firstIndex)
|
||||
{
|
||||
VarDeclaration * vd = (VarDeclaration *)fields.data[firstIndex];
|
||||
VarDeclaration * vd = fields.tdata()[firstIndex];
|
||||
/* If it is a zero-length field, AND we can't find an earlier non-zero
|
||||
* sized field with the same offset, we assume it's not part of a union.
|
||||
*/
|
||||
@@ -273,7 +279,7 @@ int AggregateDeclaration::numFieldsInUnion(int firstIndex)
|
||||
int count = 1;
|
||||
for (size_t i = firstIndex+1; i < fields.dim; ++i)
|
||||
{
|
||||
VarDeclaration * v = (VarDeclaration *)fields.data[i];
|
||||
VarDeclaration * v = fields.tdata()[i];
|
||||
// If offsets are different, they are not in the same union
|
||||
if (v->offset != vd->offset)
|
||||
break;
|
||||
@@ -366,7 +372,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
//printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
|
||||
s->addMember(sc, this, 1);
|
||||
}
|
||||
@@ -387,7 +393,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
* resolve individual members like enums.
|
||||
*/
|
||||
for (size_t i = 0; i < members_dim; i++)
|
||||
{ Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
{ Dsymbol *s = members->tdata()[i];
|
||||
/* There are problems doing this in the general case because
|
||||
* Scope keeps track of things like 'offset'
|
||||
*/
|
||||
@@ -400,7 +406,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < members_dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
s->semantic(sc2);
|
||||
#if 0
|
||||
if (sizeok == 2)
|
||||
@@ -588,7 +594,7 @@ void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writenl();
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
|
||||
buf->writestring(" ");
|
||||
s->toCBuffer(buf, hgs);
|
||||
|
||||
@@ -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
|
||||
@@ -16,6 +16,7 @@
|
||||
#if !IN_LLVM
|
||||
#endif
|
||||
#include "root.h"
|
||||
#include "aav.h"
|
||||
#include "rmem.h"
|
||||
#include "stringtable.h"
|
||||
#include "mars.h"
|
||||
@@ -280,6 +281,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)
|
||||
@@ -289,12 +292,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();
|
||||
@@ -307,7 +319,7 @@ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
|
||||
{
|
||||
if (i)
|
||||
buf->writeByte(',');
|
||||
Object *o = (Object *)args->data[i];
|
||||
Object *o = (*args)[i];
|
||||
ObjectToCBuffer(buf, hgs, o);
|
||||
}
|
||||
}
|
||||
@@ -1721,6 +1733,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)
|
||||
{
|
||||
@@ -1728,8 +1753,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())
|
||||
@@ -1749,14 +1784,14 @@ Lconst:
|
||||
|
||||
#if DMDV2
|
||||
MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
||||
Objects *dedtypes)
|
||||
Objects *dedtypes, unsigned *wildmatch)
|
||||
{
|
||||
#if 0
|
||||
printf("TypeDArray::deduceType()\n");
|
||||
printf("\tthis = %d, ", ty); print();
|
||||
printf("\ttparam = %d, ", tparam->ty); tparam->print();
|
||||
#endif
|
||||
return Type::deduceType(sc, tparam, parameters, dedtypes);
|
||||
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2911,7 +2946,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)
|
||||
@@ -3022,14 +3057,14 @@ MATCH TemplateValueParameter::matchArg(Scope *sc,
|
||||
Object *oarg;
|
||||
|
||||
if (i < tiargs->dim)
|
||||
oarg = (Object *)tiargs->data[i];
|
||||
oarg = tiargs->tdata()[i];
|
||||
else
|
||||
{ // Get default argument instead
|
||||
oarg = defaultArg(loc, sc);
|
||||
if (!oarg)
|
||||
{ assert(i < dedtypes->dim);
|
||||
// It might have already been deduced
|
||||
oarg = (Object *)dedtypes->data[i];
|
||||
oarg = dedtypes->tdata()[i];
|
||||
if (!oarg)
|
||||
goto Lnomatch;
|
||||
}
|
||||
@@ -3043,7 +3078,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc,
|
||||
|
||||
if (specValue)
|
||||
{
|
||||
if (!ei || ei == edummy)
|
||||
if (!ei || _aaGetRvalue(edummies, ei->type) == ei)
|
||||
goto Lnomatch;
|
||||
|
||||
Expression *e = specValue;
|
||||
@@ -3128,9 +3163,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;
|
||||
}
|
||||
@@ -3469,6 +3505,11 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
* (if we havetempdecl, then tiargs is already evaluated)
|
||||
*/
|
||||
semanticTiargs(sc);
|
||||
if (arrayObjectIsError(tiargs))
|
||||
{ inst = this;
|
||||
//printf("error return %p, %d\n", tempdecl, global.errors);
|
||||
return; // error recovery
|
||||
}
|
||||
|
||||
tempdecl = findTemplateDeclaration(sc);
|
||||
if (tempdecl)
|
||||
@@ -4367,6 +4408,8 @@ Identifier *TemplateInstance::genIdent()
|
||||
{ ea->error("tuple is not a valid template value argument");
|
||||
continue;
|
||||
}
|
||||
if (ea->op == TOKerror)
|
||||
continue;
|
||||
#if 1
|
||||
/* Use deco that matches what it would be for a function parameter
|
||||
*/
|
||||
@@ -4572,7 +4615,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;
|
||||
@@ -4595,7 +4638,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)
|
||||
@@ -4613,9 +4656,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;
|
||||
}
|
||||
}
|
||||
@@ -4628,11 +4671,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;
|
||||
}
|
||||
}
|
||||
@@ -4653,7 +4696,7 @@ void TemplateInstance::toObjFile(int multiobj)
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
s->toObjFile(multiobj);
|
||||
}
|
||||
}
|
||||
@@ -4671,7 +4714,7 @@ void TemplateInstance::inlineScan()
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
s->inlineScan();
|
||||
}
|
||||
}
|
||||
@@ -4694,7 +4737,7 @@ void TemplateInstance::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (i)
|
||||
buf->writeByte(',');
|
||||
Object *oarg = (Object *)args->data[i];
|
||||
Object *oarg = (*args)[i];
|
||||
ObjectToCBuffer(buf, hgs, oarg);
|
||||
}
|
||||
nest--;
|
||||
@@ -4798,7 +4841,7 @@ void TemplateInstance::printInstantiationTrace()
|
||||
|
||||
TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual,
|
||||
Identifiers *idents, Objects *tiargs)
|
||||
: TemplateInstance(loc, (Identifier *)idents->data[idents->dim - 1])
|
||||
: TemplateInstance(loc, idents->tdata()[idents->dim - 1])
|
||||
{
|
||||
//printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : "");
|
||||
this->ident = ident;
|
||||
@@ -4814,7 +4857,7 @@ Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
|
||||
ids->setDim(idents->dim);
|
||||
for (size_t i = 0; i < idents->dim; i++)
|
||||
{ // Matches TypeQualified::syntaxCopyHelper()
|
||||
Identifier *id = (Identifier *)idents->data[i];
|
||||
Identifier *id = idents->tdata()[i];
|
||||
if (id->dyncast() == DYNCAST_DSYMBOL)
|
||||
{
|
||||
TemplateInstance *ti = (TemplateInstance *)id;
|
||||
@@ -4883,7 +4926,7 @@ void TemplateMixin::semantic(Scope *sc)
|
||||
else
|
||||
{
|
||||
i = 1;
|
||||
id = (Identifier *)idents->data[0];
|
||||
id = idents->tdata()[0];
|
||||
switch (id->dyncast())
|
||||
{
|
||||
case DYNCAST_IDENTIFIER:
|
||||
@@ -4906,7 +4949,7 @@ void TemplateMixin::semantic(Scope *sc)
|
||||
{
|
||||
if (!s)
|
||||
break;
|
||||
id = (Identifier *)idents->data[i];
|
||||
id = idents->tdata()[i];
|
||||
s = s->searchX(loc, sc, id);
|
||||
}
|
||||
if (!s)
|
||||
@@ -4954,7 +4997,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);
|
||||
@@ -5190,9 +5233,11 @@ int TemplateMixin::oneMember(Dsymbol **ps)
|
||||
int TemplateMixin::hasPointers()
|
||||
{
|
||||
//printf("TemplateMixin::hasPointers() %s\n", toChars());
|
||||
|
||||
if (members)
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
//printf(" s = %s %s\n", s->kind(), s->toChars());
|
||||
if (s->hasPointers())
|
||||
{
|
||||
|
||||
@@ -198,7 +198,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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user