Merge dmd-1.073.

This commit is contained in:
kai
2012-02-23 20:41:22 +01:00
parent 53f9964b95
commit a23b837ebd
38 changed files with 2262 additions and 1340 deletions

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -91,7 +91,7 @@ enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
break;
case PROTprivate:
access = PROTnone; // private members of base class not accessible
access_ret = PROTnone; // private members of base class not accessible
break;
case PROTpackage:

View File

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

@@ -0,0 +1,165 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "mars.h"
#include "expression.h"
/**************************************
* An Expression tree walker that will visit each Expression e in the tree,
* in depth-first evaluation order, and call fp(e,param) on it.
* fp() signals whether the walking continues with its return value:
* Returns:
* 0 continue
* 1 done
* It's a bit slower than using virtual functions, but more encapsulated and less brittle.
* Creating an iterator for this would be much more complex.
*/
typedef int (*fp_t)(Expression *, void *);
int Expression::apply(fp_t fp, void *param)
{
return (*fp)(this, param);
}
/******************************
* Perform apply() on an array of Expressions.
*/
int arrayExpressionApply(Expressions *a, fp_t fp, void *param)
{
//printf("arrayExpressionApply(%p)\n", a);
if (a)
{
for (size_t i = 0; i < a->dim; i++)
{ Expression *e = (*a)[i];
if (e)
{
if (e->apply(fp, param))
return 1;
}
}
}
return 0;
}
int NewExp::apply(int (*fp)(Expression *, void *), void *param)
{
//printf("NewExp::apply(): %s\n", toChars());
return ((thisexp ? thisexp->apply(fp, param) : 0) ||
arrayExpressionApply(newargs, fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param));
}
int NewAnonClassExp::apply(int (*fp)(Expression *, void *), void *param)
{
//printf("NewAnonClassExp::apply(): %s\n", toChars());
return ((thisexp ? thisexp->apply(fp, param) : 0) ||
arrayExpressionApply(newargs, fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param));
}
int UnaExp::apply(fp_t fp, void *param)
{
return e1->apply(fp, param) ||
(*fp)(this, param);
}
int BinExp::apply(fp_t fp, void *param)
{
return e1->apply(fp, param) ||
e2->apply(fp, param) ||
(*fp)(this, param);
}
int AssertExp::apply(fp_t fp, void *param)
{
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
(msg ? msg->apply(fp, param) : 0) ||
(*fp)(this, param);
}
int CallExp::apply(fp_t fp, void *param)
{
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param);
}
int ArrayExp::apply(fp_t fp, void *param)
{
//printf("ArrayExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param);
}
int SliceExp::apply(fp_t fp, void *param)
{
return e1->apply(fp, param) ||
(lwr ? lwr->apply(fp, param) : 0) ||
(upr ? upr->apply(fp, param) : 0) ||
(*fp)(this, param);
}
int ArrayLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(elements, fp, param) ||
(*fp)(this, param);
}
int AssocArrayLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(keys, fp, param) ||
arrayExpressionApply(values, fp, param) ||
(*fp)(this, param);
}
int StructLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(elements, fp, param) ||
(*fp)(this, param);
}
int TupleExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(exps, fp, param) ||
(*fp)(this, param);
}
int CondExp::apply(fp_t fp, void *param)
{
return econd->apply(fp, param) ||
e1->apply(fp, param) ||
e2->apply(fp, param) ||
(*fp)(this, param);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -470,6 +470,7 @@ void AliasDeclaration::semantic(Scope *sc)
#endif
storage_class |= sc->stc & STCdeprecated;
protection = sc->protection;
// Given:
// alias foo.bar.abc def;

View File

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

View File

@@ -28,6 +28,9 @@
* t delegate() { return expr; }
*/
int lambdaSetParent(Expression *e, void *param);
int lambdaCheckForNestedRef(Expression *e, void *param);
Expression *Expression::toDelegate(Scope *sc, Type *t)
{
//printf("Expression::toDelegate(t = %s) %s\n", t->toChars(), toChars());
@@ -35,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);
}

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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++;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -27,7 +27,7 @@
Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId,
int isstatic)
: Dsymbol(id)
: Dsymbol()
{
assert(id);
this->loc = loc;
@@ -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();
}

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -28,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; }
};

View File

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

View File

@@ -39,15 +39,29 @@ struct InlineCostState
};
const int COST_MAX = 250;
const int STATEMENT_COST = 0x1000;
const int STATEMENT_COST_MAX = 250 * 0x1000;
// STATEMENT_COST be power of 2 and greater than COST_MAX
//static assert((STATEMENT_COST & (STATEMENT_COST - 1)) == 0);
//static assert(STATEMENT_COST > COST_MAX);
bool tooCostly(int cost) { return ((cost & (STATEMENT_COST - 1)) >= COST_MAX); }
int expressionInlineCost(Expression *e, InlineCostState *ics);
int Statement::inlineCost(InlineCostState *ics)
{
//printf("Statement::inlineCost = %d\n", COST_MAX);
//printf("%p\n", isScopeStatement());
//printf("%s\n", toChars());
return COST_MAX; // default is we can't inline it
}
int ExpStatement::inlineCost(InlineCostState *ics)
{
return exp ? exp->inlineCost(ics) : 0;
return expressionInlineCost(exp, ics);
//return exp ? exp->inlineCost(ics) : 0;
}
int CompoundStatement::inlineCost(InlineCostState *ics)
@@ -58,10 +72,11 @@ int CompoundStatement::inlineCost(InlineCostState *ics)
if (s)
{
cost += s->inlineCost(ics);
if (cost >= COST_MAX)
if (tooCostly(cost))
break;
}
}
//printf("CompoundStatement::inlineCost = %d\n", cost);
return cost;
}
@@ -73,13 +88,18 @@ int UnrolledLoopStatement::inlineCost(InlineCostState *ics)
if (s)
{
cost += s->inlineCost(ics);
if (cost >= COST_MAX)
if (tooCostly(cost))
break;
}
}
return cost;
}
int ScopeStatement::inlineCost(InlineCostState *ics)
{
return statement ? 1 + statement->inlineCost(ics) : 1;
}
int IfStatement::inlineCost(InlineCostState *ics)
{
int cost;
@@ -92,7 +112,7 @@ int IfStatement::inlineCost(InlineCostState *ics)
return COST_MAX;
#endif
cost = condition->inlineCost(ics);
cost = expressionInlineCost(condition, ics);
#if !IN_LLVM
/* Specifically allow:
@@ -121,6 +141,7 @@ int IfStatement::inlineCost(InlineCostState *ics)
cost += elsebody->inlineCost(ics);
ics->nested -= 1;
}
//printf("IfStatement::inlineCost = %d\n", cost);
return cost;
}
@@ -131,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();

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
}

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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;

View File

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

View File

@@ -347,7 +347,7 @@ char *Port::strupr(char *s)
#include <assert.h>
static double zero = 0;
double Port::nan = NAN;
double Port::nan = copysign(NAN, 1.0);
double Port::infinity = 1 / zero;
double Port::dbl_max = 1.7976931348623157e308;
double Port::dbl_min = 5e-324;
@@ -362,14 +362,7 @@ static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
// gcc nan's have the sign bit set by default, so turn it off
// Need the volatile to prevent gcc from doing incorrect
// constant folding.
volatile long double foo;
foo = NAN;
if (signbit(foo)) // signbit sometimes, not always, set
foo = -foo; // turn off sign bit
Port::nan = foo;
assert(!signbit(Port::nan));
#if __FreeBSD__ && __i386__
// LDBL_MAX comes out as infinity. Fix.

34
dmd/sideeffect.c Normal file
View 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);
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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())
{

View File

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