mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-01 23:50:43 +03:00
Merge dmdfe 2.053beta
This commit is contained in:
parent
928fa9c4de
commit
462cdda4ae
39 changed files with 2441 additions and 891 deletions
|
@ -100,6 +100,8 @@ struct AggregateDeclaration : ScopeDsymbol
|
|||
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
|
||||
Type *getType();
|
||||
void addField(Scope *sc, VarDeclaration *v);
|
||||
int firstFieldInUnion(int indx); // first field in union that includes indx
|
||||
int numFieldsInUnion(int firstIndex); // #fields in union starting at index
|
||||
int isDeprecated(); // is aggregate deprecated?
|
||||
FuncDeclaration *buildDtor(Scope *sc);
|
||||
int isNested();
|
||||
|
|
|
@ -352,7 +352,7 @@ Expression *BinExp::arrayOp(Scope *sc)
|
|||
*/
|
||||
TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
|
||||
//printf("ftype: %s\n", ftype->toChars());
|
||||
fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
|
||||
fd = new FuncDeclaration(loc, 0, Lexer::idPool(name), STCundefined, ftype);
|
||||
fd->fbody = fbody;
|
||||
fd->protection = PROTpublic;
|
||||
fd->linkage = LINKd;
|
||||
|
|
|
@ -737,6 +737,12 @@ void AnonDeclaration::semantic(Scope *sc)
|
|||
{
|
||||
//printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
|
||||
|
||||
if (sem == 1)
|
||||
{ //printf("already completed\n");
|
||||
scope = NULL;
|
||||
return; // semantic() already completed
|
||||
}
|
||||
|
||||
Scope *scx = NULL;
|
||||
if (scope)
|
||||
{ sc = scope;
|
||||
|
@ -1001,6 +1007,8 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
args->data[0] = (void *)e;
|
||||
if (e->op == TOKerror)
|
||||
goto Lnodecl;
|
||||
if (e->op != TOKstring)
|
||||
error("string expected for library name, not '%s'", e->toChars());
|
||||
else if (global.params.verbose)
|
||||
|
|
|
@ -44,7 +44,7 @@ enum BUILTIN FuncDeclaration::isBuiltin()
|
|||
static const char FeZe [] = "FNaNbNfeZe"; // @safe pure nothrow real function(real)
|
||||
static const char FeZe2[] = "FNaNbNeeZe"; // @trusted pure nothrow real function(real)
|
||||
|
||||
//printf("FuncDeclaration::isBuiltin() %s\n", toChars());
|
||||
//printf("FuncDeclaration::isBuiltin() %s, %d\n", toChars(), builtin);
|
||||
if (builtin == BUILTINunknown)
|
||||
{
|
||||
builtin = BUILTINnot;
|
||||
|
@ -52,7 +52,7 @@ enum BUILTIN FuncDeclaration::isBuiltin()
|
|||
{
|
||||
// If it's in the std.math package
|
||||
if (parent->ident == Id::math &&
|
||||
parent->parent && parent->parent->ident == Id::std &&
|
||||
parent->parent && (parent->parent->ident == Id::std || parent->parent->ident == Id::core) &&
|
||||
!parent->parent->parent)
|
||||
{
|
||||
//printf("deco = %s\n", type->deco);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -856,6 +856,12 @@ Expression *Expression::castTo(Scope *sc, Type *t)
|
|||
}
|
||||
|
||||
|
||||
Expression *ErrorExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Expression *RealExp::castTo(Scope *sc, Type *t)
|
||||
{ Expression *e = this;
|
||||
if (type != t)
|
||||
|
|
16
dmd2/class.c
16
dmd2/class.c
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -839,16 +839,18 @@ int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
|
|||
*poffset = 0;
|
||||
while (cd)
|
||||
{
|
||||
if (this == cd->baseClass)
|
||||
return 1;
|
||||
|
||||
/* cd->baseClass might not be set if cd is forward referenced.
|
||||
*/
|
||||
if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration())
|
||||
{
|
||||
cd->error("base class is forward referenced by %s", toChars());
|
||||
cd->semantic(NULL);
|
||||
if (!cd->baseClass)
|
||||
cd->error("base class is forward referenced by %s", toChars());
|
||||
}
|
||||
|
||||
if (this == cd->baseClass)
|
||||
return 1;
|
||||
|
||||
cd = cd->baseClass;
|
||||
}
|
||||
return 0;
|
||||
|
@ -876,14 +878,14 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
|
|||
Dsymbol *s;
|
||||
//printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
|
||||
|
||||
if (scope)
|
||||
if (scope && !symtab)
|
||||
{ Scope *sc = scope;
|
||||
sc->mustsemantic++;
|
||||
semantic(sc);
|
||||
sc->mustsemantic--;
|
||||
}
|
||||
|
||||
if (!members || !symtab || scope)
|
||||
if (!members || !symtab)
|
||||
{
|
||||
error("is forward referenced when looking for '%s'", ident->toChars());
|
||||
//*(char*)0=0;
|
||||
|
|
12
dmd2/clone.c
12
dmd2/clone.c
|
@ -143,7 +143,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
|
|||
((TypeFunction *)ftype)->isref = 1;
|
||||
#endif
|
||||
|
||||
fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype);
|
||||
fop = new FuncDeclaration(loc, 0, Id::assign, STCundefined, ftype);
|
||||
|
||||
Expression *e = NULL;
|
||||
if (postblit)
|
||||
|
@ -335,7 +335,7 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
|
|||
fparams->push(param);
|
||||
Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd);
|
||||
|
||||
fcp = new FuncDeclaration(0, 0, Id::cpctor, STCundefined, ftype);
|
||||
fcp = new FuncDeclaration(loc, 0, Id::cpctor, STCundefined, ftype);
|
||||
fcp->storage_class |= postblit->storage_class & STCdisable;
|
||||
|
||||
// Build *this = p;
|
||||
|
@ -434,7 +434,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
|||
*/
|
||||
if (e)
|
||||
{ //printf("Building __fieldPostBlit()\n");
|
||||
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__fieldPostBlit"));
|
||||
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, Lexer::idPool("__fieldPostBlit"));
|
||||
dd->storage_class |= stc;
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
postblits.shift(dd);
|
||||
|
@ -460,7 +460,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
|||
ex = new CallExp(0, ex);
|
||||
e = Expression::combine(e, ex);
|
||||
}
|
||||
PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__aggrPostBlit"));
|
||||
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, Lexer::idPool("__aggrPostBlit"));
|
||||
dd->storage_class |= stc;
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
members->push(dd);
|
||||
|
@ -534,7 +534,7 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
|
|||
*/
|
||||
if (e)
|
||||
{ //printf("Building __fieldDtor()\n");
|
||||
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
|
||||
DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__fieldDtor"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
dtors.shift(dd);
|
||||
members->push(dd);
|
||||
|
@ -559,7 +559,7 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
|
|||
ex = new CallExp(0, ex);
|
||||
e = Expression::combine(ex, e);
|
||||
}
|
||||
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
|
||||
DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__aggrDtor"));
|
||||
dd->fbody = new ExpStatement(0, e);
|
||||
members->push(dd);
|
||||
dd->semantic(sc);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -17,6 +17,7 @@ struct OutBuffer;
|
|||
struct Module;
|
||||
struct Scope;
|
||||
struct ScopeDsymbol;
|
||||
struct DebugCondition;
|
||||
#ifdef _DH
|
||||
#include "lexer.h" // dmdhg
|
||||
#endif
|
||||
|
@ -39,6 +40,7 @@ struct Condition
|
|||
virtual Condition *syntaxCopy() = 0;
|
||||
virtual int include(Scope *sc, ScopeDsymbol *s) = 0;
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
||||
virtual DebugCondition *isDebugCondition() { return NULL; }
|
||||
};
|
||||
|
||||
struct DVCondition : Condition
|
||||
|
@ -62,6 +64,7 @@ struct DebugCondition : DVCondition
|
|||
|
||||
int include(Scope *sc, ScopeDsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
DebugCondition *isDebugCondition() { return this; }
|
||||
};
|
||||
|
||||
struct VersionCondition : DVCondition
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -1381,9 +1381,12 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
|||
|
||||
dinteger_t v = e->toInteger();
|
||||
|
||||
size_t len = utf_codeLength(sz, v);
|
||||
size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, v);
|
||||
s = mem.malloc((len + 1) * sz);
|
||||
utf_encode(sz, s, v);
|
||||
if (t->ty == tn->ty)
|
||||
memcpy((unsigned char *)s, &v, sz);
|
||||
else
|
||||
utf_encode(sz, s, v);
|
||||
|
||||
// Add terminating 0
|
||||
memset((unsigned char *)s + len * sz, 0, sz);
|
||||
|
@ -1438,6 +1441,34 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
|||
es->type = type;
|
||||
e = es;
|
||||
}
|
||||
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 (int i = 0; i < es2->elements->dim; i++)
|
||||
{ Expression *es2e = (Expression *)es2->elements->data[i];
|
||||
if (es2e->op != TOKint64)
|
||||
return EXP_CANT_INTERPRET;
|
||||
dinteger_t v = es2e->toInteger();
|
||||
memcpy((unsigned char *)s + i * sz, &v, sz);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
else if (e1->op == TOKstring && e2->op == TOKarrayliteral &&
|
||||
t2->nextOf()->isintegral())
|
||||
{
|
||||
|
@ -1476,10 +1507,18 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
|||
int sz = es1->sz;
|
||||
dinteger_t v = e2->toInteger();
|
||||
|
||||
size_t len = es1->len + utf_codeLength(sz, v);
|
||||
// Is it a concatentation of homogenous types?
|
||||
// (char[] ~ char, wchar[]~wchar, or dchar[]~dchar)
|
||||
bool homoConcat = (sz == t2->size());
|
||||
size_t len = es1->len;
|
||||
len += homoConcat ? 1 : utf_codeLength(sz, v);
|
||||
|
||||
s = mem.malloc((len + 1) * sz);
|
||||
memcpy(s, es1->string, es1->len * sz);
|
||||
utf_encode(sz, (unsigned char *)s + (sz * es1->len), v);
|
||||
if (homoConcat)
|
||||
memcpy((unsigned char *)s + (sz * es1->len), &v, sz);
|
||||
else
|
||||
utf_encode(sz, (unsigned char *)s + (sz * es1->len), v);
|
||||
|
||||
// Add terminating 0
|
||||
memset((unsigned char *)s + len * sz, 0, sz);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -344,7 +344,7 @@ void TypedefDeclaration::semantic2(Scope *sc)
|
|||
{ sem = Semantic2Done;
|
||||
if (init)
|
||||
{
|
||||
init = init->semantic(sc, basetype);
|
||||
init = init->semantic(sc, basetype, WANTinterpret);
|
||||
|
||||
ExpInitializer *ie = init->isExpInitializer();
|
||||
if (ie)
|
||||
|
@ -556,7 +556,7 @@ void AliasDeclaration::semantic(Scope *sc)
|
|||
}
|
||||
}
|
||||
if (overnext)
|
||||
ScopeDsymbol::multiplyDefined(0, s, overnext);
|
||||
ScopeDsymbol::multiplyDefined(0, this, overnext);
|
||||
if (s == this)
|
||||
{
|
||||
assert(global.errors);
|
||||
|
@ -695,8 +695,11 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
|
|||
aliassym = NULL;
|
||||
onstack = 0;
|
||||
canassign = 0;
|
||||
value = NULL;
|
||||
setValueNull();
|
||||
#if DMDV2
|
||||
rundtor = NULL;
|
||||
edtor = NULL;
|
||||
#endif
|
||||
#if IN_LLVM
|
||||
aggrIndex = 0;
|
||||
|
||||
|
@ -1078,7 +1081,7 @@ Lagain:
|
|||
e = new ConstructExp(loc, e1, e);
|
||||
e->type = e1->type; // don't type check this, it would fail
|
||||
init = new ExpInitializer(loc, e);
|
||||
return;
|
||||
goto Ldtor;
|
||||
}
|
||||
else if (type->ty == Ttypedef)
|
||||
{ TypeTypedef *td = (TypeTypedef *)type;
|
||||
|
@ -1141,7 +1144,7 @@ Lagain:
|
|||
Expression *e = init->toExpression();
|
||||
if (!e)
|
||||
{
|
||||
init = init->semantic(sc, type);
|
||||
init = init->semantic(sc, type, 0); // Don't need to interpret
|
||||
e = init->toExpression();
|
||||
if (!e)
|
||||
{ error("is not a static and cannot have static initializer");
|
||||
|
@ -1155,6 +1158,8 @@ Lagain:
|
|||
Expression *e1 = new VarExp(loc, this);
|
||||
|
||||
Type *t = type->toBasetype();
|
||||
|
||||
Linit2:
|
||||
if (t->ty == Tsarray && !(storage_class & (STCref | STCout)))
|
||||
{
|
||||
ei->exp = ei->exp->semantic(sc);
|
||||
|
@ -1184,14 +1189,13 @@ Lagain:
|
|||
if (sd->ctor && // there are constructors
|
||||
ei->exp->type->ty == Tstruct && // rvalue is the same struct
|
||||
((TypeStruct *)ei->exp->type)->sym == sd &&
|
||||
ei->exp->op == TOKstar)
|
||||
ei->exp->op == TOKcall)
|
||||
{
|
||||
/* Look for form of constructor call which is:
|
||||
* *__ctmp.ctor(arguments...)
|
||||
*/
|
||||
PtrExp *pe = (PtrExp *)ei->exp;
|
||||
if (pe->e1->op == TOKcall)
|
||||
{ CallExp *ce = (CallExp *)pe->e1;
|
||||
if (1)
|
||||
{ CallExp *ce = (CallExp *)ei->exp;
|
||||
if (ce->e1->op == TOKdotvar)
|
||||
{ DotVarExp *dve = (DotVarExp *)ce->e1;
|
||||
if (dve->var->isCtorDeclaration())
|
||||
|
@ -1202,19 +1206,36 @@ Lagain:
|
|||
* variable with a bit copy of the default
|
||||
* initializer
|
||||
*/
|
||||
Expression *e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc));
|
||||
e->op = TOKblit;
|
||||
Expression *e;
|
||||
if (sd->zeroInit == 1)
|
||||
{
|
||||
e = new ConstructExp(loc, new VarExp(loc, this), new IntegerExp(loc, 0, Type::tint32));
|
||||
}
|
||||
else
|
||||
{ e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc));
|
||||
e->op = TOKblit;
|
||||
}
|
||||
e->type = t;
|
||||
ei->exp = new CommaExp(loc, e, ei->exp);
|
||||
|
||||
/* Replace __ctmp being constructed with e1
|
||||
*/
|
||||
dve->e1 = e1;
|
||||
return;
|
||||
ei->exp = ei->exp->semantic(sc);
|
||||
goto Ldtor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for ((S tmp = S()),tmp) and replace it with just S()
|
||||
*/
|
||||
Expression *e2 = ei->exp->isTemp();
|
||||
if (e2)
|
||||
{
|
||||
ei->exp = e2;
|
||||
goto Linit2;
|
||||
}
|
||||
#endif
|
||||
if (!ei->exp->implicitConvTo(type))
|
||||
{
|
||||
|
@ -1261,7 +1282,7 @@ Lagain:
|
|||
}
|
||||
else
|
||||
{
|
||||
init = init->semantic(sc, type);
|
||||
init = init->semantic(sc, type, WANTinterpret);
|
||||
}
|
||||
}
|
||||
else if (storage_class & (STCconst | STCimmutable | STCmanifest) ||
|
||||
|
@ -1334,7 +1355,7 @@ Lagain:
|
|||
}
|
||||
else if (si || ai)
|
||||
{ i2 = init->syntaxCopy();
|
||||
i2 = i2->semantic(sc, type);
|
||||
i2 = i2->semantic(sc, type, WANTinterpret);
|
||||
}
|
||||
inuse--;
|
||||
global.gag--;
|
||||
|
@ -1384,6 +1405,21 @@ Lagain:
|
|||
}
|
||||
sc = sc->pop();
|
||||
}
|
||||
|
||||
Ldtor:
|
||||
/* Build code to execute destruction, if necessary
|
||||
*/
|
||||
edtor = callScopeDtor(sc);
|
||||
if (edtor)
|
||||
{
|
||||
edtor = edtor->semantic(sc);
|
||||
|
||||
#if 0 // currently disabled because of std.stdio.stdin, stdout and stderr
|
||||
if (isDataseg() && !(storage_class & STCextern))
|
||||
error("static storage variables cannot have destructors");
|
||||
#endif
|
||||
}
|
||||
|
||||
sem = SemanticDone;
|
||||
}
|
||||
|
||||
|
@ -1400,7 +1436,7 @@ void VarDeclaration::semantic2(Scope *sc)
|
|||
printf("type = %p\n", ei->exp->type);
|
||||
}
|
||||
#endif
|
||||
init = init->semantic(sc, type);
|
||||
init = init->semantic(sc, type, WANTinterpret);
|
||||
inuse--;
|
||||
}
|
||||
sem = Semantic2Done;
|
||||
|
@ -1687,29 +1723,10 @@ int VarDeclaration::needsAutoDtor()
|
|||
{
|
||||
//printf("VarDeclaration::needsAutoDtor() %s\n", toChars());
|
||||
|
||||
if (noscope || storage_class & STCnodtor)
|
||||
if (noscope || !edtor)
|
||||
return FALSE;
|
||||
|
||||
// Destructors for structs and arrays of structs
|
||||
Type *tv = type->toBasetype();
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->dtor)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Destructors for classes
|
||||
if (storage_class & (STCauto | STCscope))
|
||||
{
|
||||
if (type->isClassHandle())
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1723,8 +1740,11 @@ Expression *VarDeclaration::callScopeDtor(Scope *sc)
|
|||
|
||||
//printf("VarDeclaration::callScopeDtor() %s\n", toChars());
|
||||
|
||||
if (noscope || storage_class & STCnodtor)
|
||||
// Destruction of STCfield's is handled by buildDtor()
|
||||
if (noscope || storage_class & (STCnodtor | STCref | STCout | STCfield))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Destructors for structs and arrays of structs
|
||||
bool array = false;
|
||||
|
@ -1759,6 +1779,11 @@ Expression *VarDeclaration::callScopeDtor(Scope *sc)
|
|||
else
|
||||
{
|
||||
e = new VarExp(loc, this);
|
||||
/* This is a hack so we can call destructors on const/immutable objects.
|
||||
* Need to add things like "const ~this()" and "immutable ~this()" to
|
||||
* fix properly.
|
||||
*/
|
||||
e->type = e->type->mutableOf();
|
||||
e = new DotVarExp(loc, e, sd->dtor, 0);
|
||||
e = new CallExp(loc, e);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -286,12 +286,23 @@ struct VarDeclaration : Declaration
|
|||
// 2: on stack, run destructor anyway
|
||||
int canassign; // it can be assigned to
|
||||
Dsymbol *aliassym; // if redone as alias to another symbol
|
||||
Expression *value; // when interpreting, this is the value
|
||||
// (NULL if value not determinable)
|
||||
|
||||
// When interpreting, these hold the value (NULL if value not determinable)
|
||||
// The various functions are used only to detect compiler CTFE bugs
|
||||
Expression *literalvalue;
|
||||
Expression *getValue() { return literalvalue; }
|
||||
void setValueNull();
|
||||
void setValueWithoutChecking(Expression *newval);
|
||||
void createRefValue(Expression *newval); // struct or array literal
|
||||
void setRefValue(Expression *newval);
|
||||
void setStackValue(Expression *newval);
|
||||
void createStackValue(Expression *newval);
|
||||
|
||||
#if DMDV2
|
||||
VarDeclaration *rundtor; // if !NULL, rundtor is tested at runtime to see
|
||||
// if the destructor should be run. Used to prevent
|
||||
// dtor calls on postblitted vars
|
||||
Expression *edtor; // if !=NULL, does the destruction of the variable
|
||||
#endif
|
||||
|
||||
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
|
||||
|
|
|
@ -566,6 +566,7 @@ void Dsymbol::error(const char *format, ...)
|
|||
|
||||
fprintf(stdmsg, "\n");
|
||||
fflush(stdmsg);
|
||||
//halt();
|
||||
}
|
||||
global.errors++;
|
||||
|
||||
|
@ -594,6 +595,7 @@ void Dsymbol::error(Loc loc, const char *format, ...)
|
|||
|
||||
fprintf(stdmsg, "\n");
|
||||
fflush(stdmsg);
|
||||
halt();
|
||||
}
|
||||
|
||||
global.errors++;
|
||||
|
@ -1223,33 +1225,10 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
|
|||
* multiple times, it gets set only once.
|
||||
*/
|
||||
if (!*pvar) // if not already initialized
|
||||
{ /* Create variable v and set it to the value of $,
|
||||
* which will be a constant.
|
||||
{ /* Create variable v and set it to the value of $
|
||||
*/
|
||||
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
|
||||
|
||||
if (ce->op == TOKvar)
|
||||
{ // if ce is const, get its initializer
|
||||
ce = fromConstInitializer(WANTvalue | WANTinterpret, ce);
|
||||
}
|
||||
|
||||
if (ce->op == TOKstring)
|
||||
{ /* It is for a string literal, so the
|
||||
* length will be a const.
|
||||
*/
|
||||
Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t);
|
||||
v->init = new ExpInitializer(0, e);
|
||||
v->storage_class |= STCstatic | STCconst;
|
||||
}
|
||||
else if (ce->op == TOKarrayliteral)
|
||||
{ /* It is for an array literal, so the
|
||||
* length will be a const.
|
||||
*/
|
||||
Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t);
|
||||
v->init = new ExpInitializer(0, e);
|
||||
v->storage_class |= STCstatic | STCconst;
|
||||
}
|
||||
else if (ce->op == TOKtuple)
|
||||
if (ce->op == TOKtuple)
|
||||
{ /* It is for an expression tuple, so the
|
||||
* length will be a const.
|
||||
*/
|
||||
|
@ -1257,6 +1236,14 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
|
|||
v->init = new ExpInitializer(0, e);
|
||||
v->storage_class |= STCstatic | STCconst;
|
||||
}
|
||||
else
|
||||
{ /* For arrays, $ will either be a compile-time constant
|
||||
* (in which case its value in set during constant-folding),
|
||||
* or a variable (in which case an expression is created in
|
||||
* toir.c).
|
||||
*/
|
||||
v->init = new VoidInitializer(0);
|
||||
}
|
||||
*pvar = v;
|
||||
}
|
||||
(*pvar)->semantic(sc);
|
||||
|
|
26
dmd2/dump.c
26
dmd2/dump.c
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -33,13 +33,16 @@ static char *type_print(Type *type)
|
|||
|
||||
void dumpExpressions(int i, Expressions *exps)
|
||||
{
|
||||
for (size_t j = 0; j < exps->dim; j++)
|
||||
{ Expression *e = (Expression *)exps->data[j];
|
||||
indent(i);
|
||||
printf("(\n");
|
||||
e->dump(i + 2);
|
||||
indent(i);
|
||||
printf(")\n");
|
||||
if (exps)
|
||||
{
|
||||
for (size_t j = 0; j < exps->dim; j++)
|
||||
{ Expression *e = (Expression *)exps->data[j];
|
||||
indent(i);
|
||||
printf("(\n");
|
||||
e->dump(i + 2);
|
||||
indent(i);
|
||||
printf(")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +137,12 @@ void DelegateExp::dump(int i)
|
|||
void BinExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %s type=%s e1=%p e2=%p\n", this, Token::toChars(op), type_print(type), e1, e2);
|
||||
const char *sop = Token::toChars(op);
|
||||
if (op == TOKblit)
|
||||
sop = "blit";
|
||||
else if (op == TOKconstruct)
|
||||
sop = "construct";
|
||||
printf("%p %s type=%s e1=%p e2=%p\n", this, sop, type_print(type), e1, e2);
|
||||
if (e1)
|
||||
e1->dump(i + 2);
|
||||
if (e2)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -487,7 +487,7 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps)
|
|||
* Call copy constructor for struct value argument.
|
||||
*/
|
||||
#if DMDV2
|
||||
Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
|
||||
Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope)
|
||||
{
|
||||
Type *tb = e->type->toBasetype();
|
||||
assert(tb->ty == Tstruct);
|
||||
|
@ -500,9 +500,10 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
|
|||
* This is not the most efficent, ideally tmp would be constructed
|
||||
* directly onto the stack.
|
||||
*/
|
||||
Identifier *idtmp = Lexer::uniqueId("__tmp");
|
||||
Identifier *idtmp = Lexer::uniqueId("__cpcttmp");
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e));
|
||||
tmp->storage_class |= STCctfe;
|
||||
tmp->noscope = noscope;
|
||||
Expression *ae = new DeclarationExp(loc, tmp);
|
||||
e = new CommaExp(loc, ae, new VarExp(loc, tmp));
|
||||
e = e->semantic(sc);
|
||||
|
@ -706,10 +707,41 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
|
|||
#if DMDV2
|
||||
if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
|
||||
{
|
||||
arg = callCpCtor(loc, sc, arg);
|
||||
if (arg->op == TOKcall)
|
||||
{
|
||||
/* The struct value returned from the function is transferred
|
||||
* to the function, so the callee should not call the destructor
|
||||
* on it.
|
||||
* ((S _ctmp = S.init), _ctmp).this(...)
|
||||
*/
|
||||
CallExp *ce = (CallExp *)arg;
|
||||
if (ce->e1->op == TOKdotvar)
|
||||
{ DotVarExp *dve = (DotVarExp *)ce->e1;
|
||||
if (dve->var->isCtorDeclaration())
|
||||
{ // It's a constructor call
|
||||
if (dve->e1->op == TOKcomma)
|
||||
{ CommaExp *comma = (CommaExp *)dve->e1;
|
||||
if (comma->e2->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)comma->e2;
|
||||
VarDeclaration *ctmp = ve->var->isVarDeclaration();
|
||||
if (ctmp)
|
||||
ctmp->noscope = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Not transferring it, so call the copy constructor
|
||||
*/
|
||||
arg = callCpCtor(loc, sc, arg, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//printf("arg: %s\n", arg->toChars());
|
||||
//printf("type: %s\n", arg->type->toChars());
|
||||
|
||||
// Convert lazy argument to a delegate
|
||||
if (p->storageClass & STClazy)
|
||||
{
|
||||
|
@ -770,7 +802,12 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
|
|||
}
|
||||
}
|
||||
|
||||
// Do not allow types that need destructors
|
||||
if (arg->type->needsDestruction())
|
||||
arg->error("cannot pass types that need destruction as variadic arguments");
|
||||
|
||||
// Convert static arrays to dynamic arrays
|
||||
// BUG: I don't think this is right for D2
|
||||
tb = arg->type->toBasetype();
|
||||
if (tb->ty == Tsarray)
|
||||
{ TypeSArray *ts = (TypeSArray *)tb;
|
||||
|
@ -783,7 +820,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
|
|||
#if DMDV2
|
||||
if (tb->ty == Tstruct)
|
||||
{
|
||||
arg = callCpCtor(loc, sc, arg);
|
||||
arg = callCpCtor(loc, sc, arg, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1251,6 +1288,7 @@ void Expression::checkPurity(Scope *sc, FuncDeclaration *f)
|
|||
// If the caller has a pure parent, then either the called func must be pure,
|
||||
// OR, they must have the same pure parent.
|
||||
if (outerfunc->isPure() && !sc->intypeof &&
|
||||
!(sc->flags & SCOPEdebug) &&
|
||||
!(f->isPure() || (calledparent == outerfunc)))
|
||||
{
|
||||
error("pure function '%s' cannot call impure function '%s'",
|
||||
|
@ -1464,6 +1502,55 @@ Expressions *Expression::arraySyntaxCopy(Expressions *exps)
|
|||
return a;
|
||||
}
|
||||
|
||||
/***************************************************
|
||||
* Recognize expressions of the form:
|
||||
* ((T v = init), v)
|
||||
* where v is a temp.
|
||||
* This is used in optimizing out unnecessary temporary generation.
|
||||
* Returns initializer expression of v if so, NULL if not.
|
||||
*/
|
||||
|
||||
Expression *Expression::isTemp()
|
||||
{
|
||||
//printf("isTemp() %s\n", toChars());
|
||||
if (op == TOKcomma)
|
||||
{ CommaExp *ec = (CommaExp *)this;
|
||||
if (ec->e1->op == TOKdeclaration &&
|
||||
ec->e2->op == TOKvar)
|
||||
{ DeclarationExp *de = (DeclarationExp *)ec->e1;
|
||||
VarExp *ve = (VarExp *)ec->e2;
|
||||
if (ve->var == de->declaration && ve->var->storage_class & STCctfe)
|
||||
{ VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
if (v && v->init)
|
||||
{
|
||||
ExpInitializer *ei = v->init->isExpInitializer();
|
||||
if (ei)
|
||||
{ Expression *e = ei->exp;
|
||||
if (e->op == TOKconstruct)
|
||||
{ ConstructExp *ce = (ConstructExp *)e;
|
||||
if (ce->e1->op == TOKvar && ((VarExp *)ce->e1)->var == ve->var)
|
||||
e = ce->e2;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* Destructors are attached to VarDeclarations.
|
||||
* Hence, if expression returns a temp that needs a destructor,
|
||||
* make sure and create a VarDeclaration for that temp.
|
||||
*/
|
||||
|
||||
Expression *Expression::addDtorHook(Scope *sc)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/******************************** IntegerExp **************************/
|
||||
|
||||
IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type)
|
||||
|
@ -3433,17 +3520,21 @@ Expression *StructLiteralExp::semantic(Scope *sc)
|
|||
else
|
||||
{
|
||||
if (v->init)
|
||||
{ e = v->init->toExpression();
|
||||
if (!e)
|
||||
{ error("cannot make expression out of initializer for %s", v->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
else if (v->scope)
|
||||
{ // Do deferred semantic analysis
|
||||
Initializer *i2 = v->init->syntaxCopy();
|
||||
i2 = i2->semantic(v->scope, v->type);
|
||||
e = i2->toExpression();
|
||||
v->scope = NULL;
|
||||
{ if (v->init->isVoidInitializer())
|
||||
e = NULL;
|
||||
else
|
||||
{ e = v->init->toExpression();
|
||||
if (!e)
|
||||
{ error("cannot make expression out of initializer for %s", v->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
else if (v->scope)
|
||||
{ // Do deferred semantic analysis
|
||||
Initializer *i2 = v->init->syntaxCopy();
|
||||
i2 = i2->semantic(v->scope, v->type, WANTinterpret);
|
||||
e = i2->toExpression();
|
||||
v->scope = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -3454,6 +3545,22 @@ Expression *StructLiteralExp::semantic(Scope *sc)
|
|||
}
|
||||
|
||||
type = stype ? stype : sd->type;
|
||||
|
||||
/* If struct requires a destructor, rewrite as:
|
||||
* (S tmp = S()),tmp
|
||||
* so that the destructor can be hung on tmp.
|
||||
*/
|
||||
if (sd->dtor)
|
||||
{
|
||||
Identifier *idtmp = Lexer::uniqueId("__sl");
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(0, this));
|
||||
tmp->storage_class |= STCctfe;
|
||||
Expression *ae = new DeclarationExp(loc, tmp);
|
||||
Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -3481,7 +3588,7 @@ Expression *StructLiteralExp::getField(Type *type, unsigned offset)
|
|||
/* If type is a static array, and e is an initializer for that array,
|
||||
* then the field initializer should be an array literal of e.
|
||||
*/
|
||||
if (e->type != type && type->ty == Tsarray)
|
||||
if (e->type->castMod(0) != type->castMod(0) && type->ty == Tsarray)
|
||||
{ TypeSArray *tsa = (TypeSArray *)type;
|
||||
uinteger_t length = tsa->dim->toInteger();
|
||||
Expressions *z = new Expressions;
|
||||
|
@ -3696,6 +3803,8 @@ Lagain:
|
|||
}
|
||||
//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
|
||||
}
|
||||
if (global.errors)
|
||||
return new ErrorExp();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4344,7 +4453,7 @@ Expression *VarExp::semantic(Scope *sc)
|
|||
v->checkNestedReference(sc, loc);
|
||||
#if DMDV2
|
||||
#if 1
|
||||
if (sc->func && !sc->intypeof)
|
||||
if (sc->func && !sc->intypeof && !(sc->flags & SCOPEdebug))
|
||||
{
|
||||
/* Given:
|
||||
* void f()
|
||||
|
@ -4551,7 +4660,8 @@ TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
|
|||
if (o->dyncast() == DYNCAST_EXPRESSION)
|
||||
{
|
||||
Expression *e = (Expression *)o;
|
||||
e = e->syntaxCopy();
|
||||
if (e->op == TOKdsymbol)
|
||||
e = e->syntaxCopy();
|
||||
exps->push(e);
|
||||
}
|
||||
else if (o->dyncast() == DYNCAST_DSYMBOL)
|
||||
|
@ -5051,8 +5161,8 @@ Expression *IsExp::semantic(Scope *sc)
|
|||
*/
|
||||
|
||||
//printf("IsExp::semantic(%s)\n", toChars());
|
||||
if (id && !(sc->flags & SCOPEstaticif))
|
||||
{ error("can only declare type aliases within static if conditionals");
|
||||
if (id && !(sc->flags & (SCOPEstaticif | SCOPEstaticassert)))
|
||||
{ error("can only declare type aliases within static if conditionals or static asserts");
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
|
@ -5693,6 +5803,8 @@ Expression *CompileExp::semantic(Scope *sc)
|
|||
#endif
|
||||
UnaExp::semantic(sc);
|
||||
e1 = resolveProperties(sc, e1);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (!e1->type->isString())
|
||||
{
|
||||
error("argument to mixin must be a string type, not %s\n", e1->type->toChars());
|
||||
|
@ -5740,7 +5852,7 @@ Expression *FileExp::semantic(Scope *sc)
|
|||
#endif
|
||||
UnaExp::semantic(sc);
|
||||
e1 = resolveProperties(sc, e1);
|
||||
e1 = e1->optimize(WANTvalue);
|
||||
e1 = e1->optimize(WANTvalue | WANTinterpret);
|
||||
if (e1->op != TOKstring)
|
||||
{ error("file name argument must be a string, not (%s)", e1->toChars());
|
||||
goto Lerror;
|
||||
|
@ -6266,6 +6378,7 @@ Expression *DotVarExp::semantic(Scope *sc)
|
|||
}
|
||||
|
||||
e1 = e1->semantic(sc);
|
||||
e1 = e1->addDtorHook(sc);
|
||||
type = var->type;
|
||||
if (!type && global.errors)
|
||||
{ // var is goofed up, just return 0
|
||||
|
@ -6435,6 +6548,8 @@ Expression *DotTemplateInstanceExp::semantic(Scope *sc)
|
|||
Expression *e = new DotIdExp(loc, e1, ti->name);
|
||||
L1:
|
||||
e = e->semantic(sc);
|
||||
if (e->op == TOKerror)
|
||||
return e;
|
||||
if (e->op == TOKdottd)
|
||||
{
|
||||
if (global.errors)
|
||||
|
@ -7219,7 +7334,7 @@ Lagain:
|
|||
{ TypeDelegate *td = (TypeDelegate *)t1;
|
||||
assert(td->next->ty == Tfunction);
|
||||
tf = (TypeFunction *)(td->next);
|
||||
if (sc->func && sc->func->isPure() && !tf->purity)
|
||||
if (sc->func && sc->func->isPure() && !tf->purity && !(sc->flags & SCOPEdebug))
|
||||
{
|
||||
error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars());
|
||||
}
|
||||
|
@ -7233,7 +7348,7 @@ Lagain:
|
|||
{
|
||||
Expression *e = new PtrExp(loc, e1);
|
||||
t1 = ((TypePointer *)t1)->next;
|
||||
if (sc->func && sc->func->isPure() && !((TypeFunction *)t1)->purity)
|
||||
if (sc->func && sc->func->isPure() && !((TypeFunction *)t1)->purity && !(sc->flags & SCOPEdebug))
|
||||
{
|
||||
error("pure function '%s' cannot call impure function pointer '%s'", sc->func->toChars(), e1->toChars());
|
||||
}
|
||||
|
@ -7356,9 +7471,9 @@ int CallExp::checkSideEffect(int flag)
|
|||
* then this expression has no side effects.
|
||||
*/
|
||||
Type *t = e1->type->toBasetype();
|
||||
if (t->ty == Tfunction && ((TypeFunction *)t)->purity)
|
||||
if (t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak)
|
||||
return 0;
|
||||
if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity)
|
||||
if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity > PUREweak)
|
||||
return 0;
|
||||
#endif
|
||||
return 1;
|
||||
|
@ -7417,6 +7532,51 @@ Expression *CallExp::toLvalue(Scope *sc, Expression *e)
|
|||
return Expression::toLvalue(sc, e);
|
||||
}
|
||||
|
||||
Expression *CallExp::addDtorHook(Scope *sc)
|
||||
{
|
||||
/* Only need to add dtor hook if it's a type that needs destruction.
|
||||
* Use same logic as VarDeclaration::callScopeDtor()
|
||||
*/
|
||||
|
||||
if (e1->type && e1->type->ty == Tfunction)
|
||||
{
|
||||
TypeFunction *tf = (TypeFunction *)e1->type;
|
||||
if (tf->isref)
|
||||
return this;
|
||||
}
|
||||
|
||||
Type *tv = type->toBasetype();
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->dtor)
|
||||
{ /* Type needs destruction, so declare a tmp
|
||||
* which the back end will recognize and call dtor on
|
||||
*/
|
||||
if (e1->op == TOKdotvar)
|
||||
{
|
||||
DotVarExp* dve = (DotVarExp*)e1;
|
||||
if (dve->e1->isTemp() != NULL)
|
||||
goto Lnone; // already got a tmp
|
||||
}
|
||||
|
||||
Identifier *idtmp = Lexer::uniqueId("__tmpfordtor");
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(loc, this));
|
||||
tmp->storage_class |= STCctfe;
|
||||
Expression *ae = new DeclarationExp(loc, tmp);
|
||||
Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
Lnone:
|
||||
return this;
|
||||
}
|
||||
|
||||
void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (e1->op == TOKtype)
|
||||
|
@ -7779,6 +7939,8 @@ Expression *DeleteExp::semantic(Scope *sc)
|
|||
UnaExp::semantic(sc);
|
||||
e1 = resolveProperties(sc, e1);
|
||||
e1 = e1->toLvalue(sc, NULL);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
type = Type::tvoid;
|
||||
|
||||
tb = e1->type->toBasetype();
|
||||
|
@ -8591,6 +8753,7 @@ Expression *CommaExp::semantic(Scope *sc)
|
|||
{
|
||||
if (!type)
|
||||
{ BinExp::semanticp(sc);
|
||||
e1 = e1->addDtorHook(sc);
|
||||
type = e2->type;
|
||||
}
|
||||
return this;
|
||||
|
@ -8656,6 +8819,12 @@ int CommaExp::checkSideEffect(int flag)
|
|||
}
|
||||
}
|
||||
|
||||
Expression *CommaExp::addDtorHook(Scope *sc)
|
||||
{
|
||||
e2 = e2->addDtorHook(sc);
|
||||
return this;
|
||||
}
|
||||
|
||||
/************************** IndexExp **********************************/
|
||||
|
||||
// e1 [ e2 ]
|
||||
|
@ -8894,7 +9063,7 @@ Expression *PostExp::semantic(Scope *sc)
|
|||
/* Rewrite as:
|
||||
* auto tmp = e1; ++e1; tmp
|
||||
*/
|
||||
Identifier *id = Lexer::uniqueId("__tmp");
|
||||
Identifier *id = Lexer::uniqueId("__pitmp");
|
||||
ExpInitializer *ei = new ExpInitializer(loc, e1);
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, e1->type, id, ei);
|
||||
Expression *ea = new DeclarationExp(loc, tmp);
|
||||
|
@ -9180,16 +9349,28 @@ Expression *AssignExp::semantic(Scope *sc)
|
|||
sd->cpctor)
|
||||
{ /* We have a copy constructor for this
|
||||
*/
|
||||
// Scan past commma's
|
||||
Expression *ec = NULL;
|
||||
while (e2->op == TOKcomma)
|
||||
{ CommaExp *ecomma = (CommaExp *)e2;
|
||||
e2 = ecomma->e2;
|
||||
if (ec)
|
||||
ec = new CommaExp(ecomma->loc, ec, ecomma->e1);
|
||||
else
|
||||
ec = ecomma->e1;
|
||||
}
|
||||
if (e2->op == TOKquestion)
|
||||
{ /* Write as:
|
||||
* a ? e1 = b : e1 = c;
|
||||
*/
|
||||
CondExp *ec = (CondExp *)e2;
|
||||
AssignExp *ea1 = new AssignExp(ec->e1->loc, e1, ec->e1);
|
||||
CondExp *econd = (CondExp *)e2;
|
||||
AssignExp *ea1 = new AssignExp(econd->e1->loc, e1, econd->e1);
|
||||
ea1->op = op;
|
||||
AssignExp *ea2 = new AssignExp(ec->e1->loc, e1, ec->e2);
|
||||
AssignExp *ea2 = new AssignExp(econd->e1->loc, e1, econd->e2);
|
||||
ea2->op = op;
|
||||
Expression *e = new CondExp(loc, ec->econd, ea1, ea2);
|
||||
Expression *e = new CondExp(loc, econd->econd, ea1, ea2);
|
||||
if (ec)
|
||||
e = new CommaExp(loc, ec, e);
|
||||
return e->semantic(sc);
|
||||
}
|
||||
else if (e2->op == TOKvar ||
|
||||
|
@ -9202,8 +9383,33 @@ Expression *AssignExp::semantic(Scope *sc)
|
|||
*/
|
||||
Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
|
||||
e = new CallExp(loc, e, e2);
|
||||
if (ec)
|
||||
e = new CommaExp(loc, ec, e);
|
||||
return e->semantic(sc);
|
||||
}
|
||||
else if (e2->op == TOKcall)
|
||||
{
|
||||
/* The struct value returned from the function is transferred
|
||||
* so should not call the destructor on it.
|
||||
* ((S _ctmp = S.init), _ctmp).this(...)
|
||||
*/
|
||||
CallExp *ce = (CallExp *)e2;
|
||||
if (ce->e1->op == TOKdotvar)
|
||||
{ DotVarExp *dve = (DotVarExp *)ce->e1;
|
||||
if (dve->var->isCtorDeclaration())
|
||||
{ // It's a constructor call
|
||||
if (dve->e1->op == TOKcomma)
|
||||
{ CommaExp *comma = (CommaExp *)dve->e1;
|
||||
if (comma->e2->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)comma->e2;
|
||||
VarDeclaration *ctmp = ve->var->isVarDeclaration();
|
||||
if (ctmp)
|
||||
ctmp->noscope = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9560,6 +9766,7 @@ Expression *CatAssignExp::semantic(Scope *sc)
|
|||
}
|
||||
else if (tb1->ty == Tarray &&
|
||||
(tb1next->ty == Tchar || tb1next->ty == Twchar) &&
|
||||
e2->type->ty != tb1next->ty &&
|
||||
e2->implicitConvTo(Type::tdchar)
|
||||
)
|
||||
{ // Append dchar to char[] or wchar[]
|
||||
|
@ -10448,6 +10655,35 @@ Expression *PowExp::semantic(Scope *sc)
|
|||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
// Replace x ^^ 0 or x^^0.0 by (x, 1)
|
||||
if ((e2->op == TOKint64 && e2->toInteger() == 0) ||
|
||||
(e2->op == TOKfloat64 && e2->toReal() == 0.0))
|
||||
{
|
||||
if (e1->op == TOKint64)
|
||||
e = new IntegerExp(loc, 1, e1->type);
|
||||
else
|
||||
e = new RealExp(loc, 1.0, e1->type);
|
||||
|
||||
typeCombine(sc);
|
||||
e = new CommaExp(loc, e1, e);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
// Replace x ^^ 1 or x^^1.0 by (x)
|
||||
if ((e2->op == TOKint64 && e2->toInteger() == 1) ||
|
||||
(e2->op == TOKfloat64 && e2->toReal() == 1.0))
|
||||
{
|
||||
typeCombine(sc);
|
||||
return e1;
|
||||
}
|
||||
// Replace x ^^ -1.0 by (1.0 / x)
|
||||
if ((e2->op == TOKfloat64 && e2->toReal() == -1.0))
|
||||
{
|
||||
typeCombine(sc);
|
||||
e = new DivExp(loc, new RealExp(loc, 1.0, e2->type), e1);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
// All other negative integral powers are illegal
|
||||
if ((e1->type->isintegral()) && (e2->op == TOKint64) && (sinteger_t)e2->toInteger() < 0)
|
||||
{
|
||||
|
@ -10469,7 +10705,7 @@ Expression *PowExp::semantic(Scope *sc)
|
|||
typeCombine(sc);
|
||||
// Replace x^^2 with (tmp = x, tmp*tmp)
|
||||
// Replace x^^3 with (tmp = x, tmp*tmp*tmp)
|
||||
Identifier *idtmp = Lexer::uniqueId("__tmp");
|
||||
Identifier *idtmp = Lexer::uniqueId("__powtmp");
|
||||
VarDeclaration *tmp = new VarDeclaration(loc, e1->type->toBasetype(), idtmp, new ExpInitializer(0, e1));
|
||||
tmp->storage_class = STCctfe;
|
||||
Expression *ve = new VarExp(loc, tmp);
|
||||
|
@ -10744,13 +10980,21 @@ Expression *OrOrExp::semantic(Scope *sc)
|
|||
e2 = resolveProperties(sc, e2);
|
||||
e2 = e2->checkToPointer();
|
||||
|
||||
type = Type::tboolean;
|
||||
if (e2->type->ty == Tvoid)
|
||||
type = Type::tvoid;
|
||||
else
|
||||
{
|
||||
e2 = e2->checkToBoolean(sc);
|
||||
type = Type::tboolean;
|
||||
}
|
||||
if (e2->op == TOKtype || e2->op == TOKimport)
|
||||
{ error("%s is not an expression", e2->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -10811,13 +11055,21 @@ Expression *AndAndExp::semantic(Scope *sc)
|
|||
e2 = resolveProperties(sc, e2);
|
||||
e2 = e2->checkToPointer();
|
||||
|
||||
type = Type::tboolean;
|
||||
if (e2->type->ty == Tvoid)
|
||||
type = Type::tvoid;
|
||||
else
|
||||
{
|
||||
e2 = e2->checkToBoolean(sc);
|
||||
type = Type::tboolean;
|
||||
}
|
||||
if (e2->op == TOKtype || e2->op == TOKimport)
|
||||
{ error("%s is not an expression", e2->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -46,6 +46,7 @@ struct InterState;
|
|||
struct Symbol; // back end symbol
|
||||
#endif
|
||||
struct OverloadSet;
|
||||
struct Initializer;
|
||||
#if IN_LLVM
|
||||
struct AssignExp;
|
||||
#endif
|
||||
|
@ -88,6 +89,15 @@ FuncDeclaration *hasThis(Scope *sc);
|
|||
Expression *fromConstInitializer(int result, Expression *e);
|
||||
int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow);
|
||||
|
||||
/* Interpreter: what form of return value expression is required?
|
||||
*/
|
||||
enum CtfeGoal
|
||||
{ ctfeNeedRvalue, // Must return an Rvalue
|
||||
ctfeNeedLvalue, // Must return an Lvalue
|
||||
ctfeNeedAnyValue, // Can return either an Rvalue or an Lvalue
|
||||
ctfeNeedNothing // The return value is not required
|
||||
};
|
||||
|
||||
struct IntRange
|
||||
{ uinteger_t imin;
|
||||
uinteger_t imax;
|
||||
|
@ -144,10 +154,12 @@ struct Expression : Object
|
|||
void checkPurity(Scope *sc, FuncDeclaration *f);
|
||||
void checkSafety(Scope *sc, FuncDeclaration *f);
|
||||
virtual Expression *checkToBoolean(Scope *sc);
|
||||
virtual Expression *addDtorHook(Scope *sc);
|
||||
Expression *checkToPointer();
|
||||
Expression *addressOf(Scope *sc);
|
||||
Expression *deref();
|
||||
Expression *integralPromotions(Scope *sc);
|
||||
Expression *isTemp();
|
||||
|
||||
Expression *toDelegate(Scope *sc, Type *t);
|
||||
virtual void scanForNestedRef(Scope *sc);
|
||||
|
@ -155,9 +167,12 @@ struct Expression : Object
|
|||
virtual Expression *optimize(int result);
|
||||
#define WANTflags 1
|
||||
#define WANTvalue 2
|
||||
// A compile-time result is required. Give an error if not possible
|
||||
#define WANTinterpret 4
|
||||
// Same as WANTvalue, but also expand variables as far as possible
|
||||
#define WANTexpand 8
|
||||
|
||||
virtual Expression *interpret(InterState *istate);
|
||||
virtual Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
|
||||
virtual int isConst();
|
||||
virtual int isBool(int result);
|
||||
|
@ -183,6 +198,7 @@ struct Expression : Object
|
|||
#if IN_DMD
|
||||
// Back end
|
||||
virtual elem *toElem(IRState *irs);
|
||||
elem *toElemDtor(IRState *irs);
|
||||
virtual dt_t **toDt(dt_t **pdt);
|
||||
#endif
|
||||
|
||||
|
@ -205,7 +221,7 @@ struct IntegerExp : Expression
|
|||
IntegerExp(dinteger_t value);
|
||||
int equals(Object *o);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
char *toChars();
|
||||
void dump(int indent);
|
||||
IntRange getIntRange();
|
||||
|
@ -233,6 +249,7 @@ struct ErrorExp : IntegerExp
|
|||
ErrorExp();
|
||||
|
||||
Expression *implicitCastTo(Scope *sc, Type *t);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Expression *toLvalue(Scope *sc, Expression *e);
|
||||
};
|
||||
|
@ -244,7 +261,7 @@ struct RealExp : Expression
|
|||
RealExp(Loc loc, real_t value, Type *type);
|
||||
int equals(Object *o);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
char *toChars();
|
||||
dinteger_t toInteger();
|
||||
uinteger_t toUInteger();
|
||||
|
@ -272,7 +289,7 @@ struct ComplexExp : Expression
|
|||
ComplexExp(Loc loc, complex_t value, Type *type);
|
||||
int equals(Object *o);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
char *toChars();
|
||||
dinteger_t toInteger();
|
||||
uinteger_t toUInteger();
|
||||
|
@ -336,7 +353,7 @@ struct ThisExp : Expression
|
|||
|
||||
ThisExp(Loc loc);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int isBool(int result);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int isLvalue();
|
||||
|
@ -380,7 +397,7 @@ struct NullExp : Expression
|
|||
void toMangleBuffer(OutBuffer *buf);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
dt_t **toDt(dt_t **pdt);
|
||||
|
@ -405,7 +422,7 @@ struct StringExp : Expression
|
|||
int equals(Object *o);
|
||||
char *toChars();
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
size_t length();
|
||||
StringExp *toUTF8(Scope *sc);
|
||||
Expression *implicitCastTo(Scope *sc, Type *t);
|
||||
|
@ -443,7 +460,7 @@ struct TupleExp : Expression
|
|||
void checkEscape();
|
||||
int checkSideEffect(int flag);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
|
@ -474,7 +491,7 @@ struct ArrayLiteralExp : Expression
|
|||
void toMangleBuffer(OutBuffer *buf);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
int canThrow(bool mustNotThrow);
|
||||
|
@ -510,7 +527,7 @@ struct AssocArrayLiteralExp : Expression
|
|||
void toMangleBuffer(OutBuffer *buf);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
int canThrow(bool mustNotThrow);
|
||||
|
@ -549,7 +566,7 @@ struct StructLiteralExp : Expression
|
|||
void toMangleBuffer(OutBuffer *buf);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int isLvalue();
|
||||
Expression *toLvalue(Scope *sc, Expression *e);
|
||||
int canThrow(bool mustNotThrow);
|
||||
|
@ -636,7 +653,7 @@ struct NewExp : Expression
|
|||
Type *newtype, Expressions *arguments);
|
||||
Expression *syntaxCopy();
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
Expression *optimize(int result);
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
|
@ -700,7 +717,7 @@ struct SymOffExp : SymbolExp
|
|||
|
||||
SymOffExp(Loc loc, Declaration *var, unsigned offset, int hasOverloads = 0);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void checkEscape();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int isConst();
|
||||
|
@ -727,7 +744,7 @@ struct VarExp : SymbolExp
|
|||
int equals(Object *o);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void dump(int indent);
|
||||
char *toChars();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
@ -774,7 +791,7 @@ struct FuncExp : Expression
|
|||
FuncExp(Loc loc, FuncLiteralDeclaration *fd);
|
||||
Expression *syntaxCopy();
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
char *toChars();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
@ -801,7 +818,7 @@ struct DeclarationExp : Expression
|
|||
DeclarationExp(Loc loc, Dsymbol *declaration);
|
||||
Expression *syntaxCopy();
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int checkSideEffect(int flag);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
#if IN_DMD
|
||||
|
@ -890,7 +907,8 @@ struct UnaExp : Expression
|
|||
Expression *optimize(int result);
|
||||
void dump(int indent);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *));
|
||||
Expression *interpretCommon(InterState *istate, CtfeGoal goal,
|
||||
Expression *(*fp)(Type *, Expression *));
|
||||
int canThrow(bool mustNotThrow);
|
||||
Expression *resolveLoc(Loc loc, Scope *sc);
|
||||
|
||||
|
@ -921,9 +939,12 @@ struct BinExp : Expression
|
|||
void incompatibleTypes();
|
||||
void dump(int indent);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *));
|
||||
Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *));
|
||||
Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
|
||||
Expression *interpretCommon(InterState *istate, CtfeGoal goal,
|
||||
Expression *(*fp)(Type *, Expression *, Expression *));
|
||||
Expression *interpretCommon2(InterState *istate, CtfeGoal goal,
|
||||
Expression *(*fp)(TOK, Type *, Expression *, Expression *));
|
||||
Expression *interpretAssignCommon(InterState *istate, CtfeGoal goal,
|
||||
Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
|
||||
int canThrow(bool mustNotThrow);
|
||||
Expression *arrayOp(Scope *sc);
|
||||
|
||||
|
@ -979,7 +1000,7 @@ struct AssertExp : UnaExp
|
|||
AssertExp(Loc loc, Expression *e, Expression *msg = NULL);
|
||||
Expression *syntaxCopy();
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int checkSideEffect(int flag);
|
||||
int canThrow(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
@ -1027,7 +1048,7 @@ struct DotVarExp : UnaExp
|
|||
Expression *toLvalue(Scope *sc, Expression *e);
|
||||
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void dump(int indent);
|
||||
#if IN_DMD
|
||||
|
@ -1060,7 +1081,7 @@ struct DelegateExp : UnaExp
|
|||
|
||||
DelegateExp(Loc loc, Expression *e, FuncDeclaration *func, int hasOverloads = 0);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
@ -1104,7 +1125,7 @@ struct CallExp : UnaExp
|
|||
Expression *syntaxCopy();
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int checkSideEffect(int flag);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void dump(int indent);
|
||||
|
@ -1115,6 +1136,7 @@ struct CallExp : UnaExp
|
|||
int isLvalue();
|
||||
Expression *toLvalue(Scope *sc, Expression *e);
|
||||
int canThrow(bool mustNotThrow);
|
||||
Expression *addDtorHook(Scope *sc);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
|
@ -1143,7 +1165,7 @@ struct AddrExp : UnaExp
|
|||
#if IN_LLVM
|
||||
DValue* toElem(IRState* irs);
|
||||
llvm::Constant *toConstElem(IRState *irs);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1161,7 +1183,7 @@ struct PtrExp : UnaExp
|
|||
elem *toElem(IRState *irs);
|
||||
#endif
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
|
||||
// For operator overloading
|
||||
Identifier *opId();
|
||||
|
@ -1177,7 +1199,7 @@ struct NegExp : UnaExp
|
|||
NegExp(Loc loc, Expression *e);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
|
||||
|
@ -1207,7 +1229,7 @@ struct ComExp : UnaExp
|
|||
ComExp(Loc loc, Expression *e);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
|
||||
|
@ -1228,7 +1250,7 @@ struct NotExp : UnaExp
|
|||
NotExp(Loc loc, Expression *e);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int isBit();
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
|
@ -1244,7 +1266,7 @@ struct BoolExp : UnaExp
|
|||
BoolExp(Loc loc, Expression *e, Type *type);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int isBit();
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
|
@ -1284,7 +1306,7 @@ struct CastExp : UnaExp
|
|||
MATCH implicitConvTo(Type *t);
|
||||
IntRange getIntRange();
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int checkSideEffect(int flag);
|
||||
void checkEscape();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
@ -1322,7 +1344,7 @@ struct SliceExp : UnaExp
|
|||
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void dump(int indent);
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
|
@ -1346,7 +1368,7 @@ struct ArrayLengthExp : UnaExp
|
|||
ArrayLengthExp(Loc loc, Expression *e1);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
|
@ -1404,9 +1426,10 @@ struct CommaExp : BinExp
|
|||
int isBool(int result);
|
||||
int checkSideEffect(int flag);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
Expression *addDtorHook(Scope *sc);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
#endif
|
||||
|
@ -1429,7 +1452,7 @@ struct IndexExp : BinExp
|
|||
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
|
||||
|
@ -1448,7 +1471,7 @@ struct PostExp : BinExp
|
|||
{
|
||||
PostExp(enum TOK op, Loc loc, Expression *e);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Identifier *opId(); // For operator overloading
|
||||
#if IN_DMD
|
||||
|
@ -1475,7 +1498,7 @@ struct AssignExp : BinExp
|
|||
AssignExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *checkToBoolean(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
Identifier *opId(); // For operator overloading
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
|
@ -1507,7 +1530,7 @@ struct op##AssignExp : BinAssignExp \
|
|||
{ \
|
||||
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
|
||||
Expression *semantic(Scope *sc); \
|
||||
Expression *interpret(InterState *istate); \
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \
|
||||
X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
|
||||
X(Expression *buildArrayLoop(Parameters *fparams);) \
|
||||
\
|
||||
|
@ -1553,7 +1576,7 @@ struct AddExp : BinExp
|
|||
AddExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
|
||||
|
@ -1577,7 +1600,7 @@ struct MinExp : BinExp
|
|||
MinExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
|
||||
|
@ -1600,7 +1623,7 @@ struct CatExp : BinExp
|
|||
CatExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
|
||||
// For operator overloading
|
||||
Identifier *opId();
|
||||
|
@ -1620,7 +1643,7 @@ struct MulExp : BinExp
|
|||
MulExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
|
||||
|
@ -1643,7 +1666,7 @@ struct DivExp : BinExp
|
|||
DivExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
IntRange getIntRange();
|
||||
|
@ -1666,7 +1689,7 @@ struct ModExp : BinExp
|
|||
ModExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
|
||||
|
@ -1700,7 +1723,7 @@ struct ShlExp : BinExp
|
|||
ShlExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
IntRange getIntRange();
|
||||
|
||||
// For operator overloading
|
||||
|
@ -1721,7 +1744,7 @@ struct ShrExp : BinExp
|
|||
ShrExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
IntRange getIntRange();
|
||||
|
||||
// For operator overloading
|
||||
|
@ -1742,7 +1765,7 @@ struct UshrExp : BinExp
|
|||
UshrExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
IntRange getIntRange();
|
||||
|
||||
// For operator overloading
|
||||
|
@ -1763,7 +1786,7 @@ struct AndExp : BinExp
|
|||
AndExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
IntRange getIntRange();
|
||||
|
@ -1787,7 +1810,7 @@ struct OrExp : BinExp
|
|||
OrExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
|
@ -1812,7 +1835,7 @@ struct XorExp : BinExp
|
|||
XorExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||
Expression *buildArrayLoop(Parameters *fparams);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
|
@ -1839,7 +1862,7 @@ struct OrOrExp : BinExp
|
|||
Expression *checkToBoolean(Scope *sc);
|
||||
int isBit();
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int checkSideEffect(int flag);
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
|
@ -1857,7 +1880,7 @@ struct AndAndExp : BinExp
|
|||
Expression *checkToBoolean(Scope *sc);
|
||||
int isBit();
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int checkSideEffect(int flag);
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
|
@ -1873,7 +1896,7 @@ struct CmpExp : BinExp
|
|||
CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int isBit();
|
||||
|
||||
// For operator overloading
|
||||
|
@ -1929,7 +1952,7 @@ struct EqualExp : BinExp
|
|||
EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
int isBit();
|
||||
|
||||
// For operator overloading
|
||||
|
@ -1954,7 +1977,7 @@ struct IdentityExp : BinExp
|
|||
Expression *semantic(Scope *sc);
|
||||
int isBit();
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
#endif
|
||||
|
@ -1974,7 +1997,7 @@ struct CondExp : BinExp
|
|||
Expression *syntaxCopy();
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *optimize(int result);
|
||||
Expression *interpret(InterState *istate);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
void checkEscape();
|
||||
void checkEscapeRef();
|
||||
int isLvalue();
|
||||
|
|
21
dmd2/func.c
21
dmd2/func.c
|
@ -288,6 +288,10 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||
if (isAbstract() && !isVirtual())
|
||||
error("non-virtual functions cannot be abstract");
|
||||
|
||||
// https://github.com/donc/dmd/commit/9f7b2f8cfe5d7482f2de7f9678c176d54abe237f#commitcomment-321724
|
||||
//if (isOverride() && !isVirtual())
|
||||
//error("cannot override a non-virtual function");
|
||||
|
||||
if ((f->isConst() || f->isImmutable()) && !isThis())
|
||||
error("without 'this' cannot be const/immutable");
|
||||
|
||||
|
@ -744,7 +748,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||
FuncDeclaration *fd = new FuncDeclaration(loc, loc,
|
||||
Id::require, STCundefined, tf);
|
||||
fd->fbody = frequire;
|
||||
Statement *s1 = new DeclarationStatement(loc, fd);
|
||||
Statement *s1 = new ExpStatement(loc, fd);
|
||||
Expression *e = new CallExp(loc, new VarExp(loc, fd, 0), (Expressions *)NULL);
|
||||
Statement *s2 = new ExpStatement(loc, e);
|
||||
frequire = new CompoundStatement(loc, s1, s2);
|
||||
|
@ -771,7 +775,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||
FuncDeclaration *fd = new FuncDeclaration(loc, loc,
|
||||
Id::ensure, STCundefined, tf);
|
||||
fd->fbody = fensure;
|
||||
Statement *s1 = new DeclarationStatement(loc, fd);
|
||||
Statement *s1 = new ExpStatement(loc, fd);
|
||||
Expression *eresult = NULL;
|
||||
if (outId)
|
||||
eresult = new IdentifierExp(loc, outId);
|
||||
|
@ -1018,7 +1022,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||
v_arguments->parent = this;
|
||||
#endif
|
||||
}
|
||||
if (f->linkage == LINKd || (parameters && parameters->dim))
|
||||
if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters)))
|
||||
{ // Declare _argptr
|
||||
#if IN_GCC
|
||||
t = d_gcc_builtin_va_list_d_type;
|
||||
|
@ -1709,7 +1713,10 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||
if (v->type->toBasetype()->ty == Tsarray)
|
||||
continue;
|
||||
|
||||
Expression *e = v->callScopeDtor(sc2);
|
||||
if (v->noscope)
|
||||
continue;
|
||||
|
||||
Expression *e = v->edtor;
|
||||
if (e)
|
||||
{ Statement *s = new ExpStatement(0, e);
|
||||
s = s->semantic(sc2);
|
||||
|
@ -1727,7 +1734,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||
{ /* Wrap the entire function body in a synchronized statement
|
||||
*/
|
||||
AggregateDeclaration *ad = isThis();
|
||||
ClassDeclaration *cd = ad ? ad->isClassDeclaration() : NULL;
|
||||
ClassDeclaration *cd = ad ? ad->isClassDeclaration() : parent->isClassDeclaration();
|
||||
|
||||
if (cd)
|
||||
{
|
||||
|
@ -3395,7 +3402,7 @@ void StaticCtorDeclaration::semantic(Scope *sc)
|
|||
VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
|
||||
v->storage_class = isSharedStaticCtorDeclaration() ? STCstatic : STCtls;
|
||||
Statements *sa = new Statements();
|
||||
Statement *s = new DeclarationStatement(0, v);
|
||||
Statement *s = new ExpStatement(0, v);
|
||||
sa->push(s);
|
||||
Expression *e = new IdentifierExp(0, id);
|
||||
e = new AddAssignExp(0, e, new IntegerExp(1));
|
||||
|
@ -3521,7 +3528,7 @@ void StaticDtorDeclaration::semantic(Scope *sc)
|
|||
VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
|
||||
v->storage_class = isSharedStaticDtorDeclaration() ? STCstatic : STCtls;
|
||||
Statements *sa = new Statements();
|
||||
Statement *s = new DeclarationStatement(0, v);
|
||||
Statement *s = new ExpStatement(0, v);
|
||||
sa->push(s);
|
||||
Expression *e = new IdentifierExp(0, id);
|
||||
e = new AddAssignExp(0, e, new IntegerExp((uint64_t)-1));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -302,6 +302,7 @@ Msgtable msgtable[] =
|
|||
|
||||
// Builtin functions
|
||||
{ "std" },
|
||||
{ "core" },
|
||||
{ "math" },
|
||||
{ "sin" },
|
||||
{ "cos" },
|
||||
|
@ -329,6 +330,7 @@ Msgtable msgtable[] =
|
|||
{ "isLazy" },
|
||||
{ "hasMember" },
|
||||
{ "identifier" },
|
||||
{ "parent" },
|
||||
{ "getMember" },
|
||||
{ "getOverloads" },
|
||||
{ "getVirtualFunctions" },
|
||||
|
|
135
dmd2/init.c
135
dmd2/init.c
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -34,7 +34,7 @@ Initializer *Initializer::syntaxCopy()
|
|||
return this;
|
||||
}
|
||||
|
||||
Initializer *Initializer::semantic(Scope *sc, Type *t)
|
||||
Initializer *Initializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ Initializer *VoidInitializer::syntaxCopy()
|
|||
}
|
||||
|
||||
|
||||
Initializer *VoidInitializer::semantic(Scope *sc, Type *t)
|
||||
Initializer *VoidInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
{
|
||||
//printf("VoidInitializer::semantic(t = %p)\n", t);
|
||||
type = t;
|
||||
|
@ -141,7 +141,7 @@ void StructInitializer::addInit(Identifier *field, Initializer *value)
|
|||
this->value.push(value);
|
||||
}
|
||||
|
||||
Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
||||
Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
|
@ -168,6 +168,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
|||
{
|
||||
if (fieldi >= ad->fields.dim)
|
||||
{ error(loc, "too many initializers for %s", ad->toChars());
|
||||
errors = 1;
|
||||
field.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
|
@ -184,6 +185,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
|||
if (!s)
|
||||
{
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
|
||||
errors = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -192,7 +194,9 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
|||
{
|
||||
if (fieldi >= ad->fields.dim)
|
||||
{
|
||||
s->error("is not a per-instance initializable field");
|
||||
error(loc, "%s.%s is not a per-instance initializable field",
|
||||
t->toChars(), s->toChars());
|
||||
errors = 1;
|
||||
break;
|
||||
}
|
||||
if (s == (Dsymbol *)ad->fields.data[fieldi])
|
||||
|
@ -201,7 +205,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
|||
}
|
||||
if (s && (v = s->isVarDeclaration()) != NULL)
|
||||
{
|
||||
val = val->semantic(sc, v->type);
|
||||
val = val->semantic(sc, v->type, needInterpret);
|
||||
value.data[i] = (void *)val;
|
||||
vars.data[i] = (void *)v;
|
||||
}
|
||||
|
@ -222,7 +226,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
|||
fd->endloc = loc;
|
||||
Expression *e = new FuncExp(loc, fd);
|
||||
ExpInitializer *ie = new ExpInitializer(loc, e);
|
||||
return ie->semantic(sc, t);
|
||||
return ie->semantic(sc, t, needInterpret);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -238,7 +242,6 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
/***************************************
|
||||
* This works by transforming a struct initializer into
|
||||
* a struct literal. In the future, the two should be the
|
||||
|
@ -246,6 +249,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
|||
*/
|
||||
Expression *StructInitializer::toExpression()
|
||||
{ Expression *e;
|
||||
size_t offset;
|
||||
|
||||
//printf("StructInitializer::toExpression() %s\n", toChars());
|
||||
if (!ad) // if fwd referenced
|
||||
|
@ -256,17 +260,110 @@ Expression *StructInitializer::toExpression()
|
|||
if (!sd)
|
||||
return NULL;
|
||||
Expressions *elements = new Expressions();
|
||||
for (size_t i = 0; i < value.dim; i++)
|
||||
elements->setDim(ad->fields.dim);
|
||||
for (int i = 0; i < elements->dim; i++)
|
||||
{
|
||||
if (field.data[i])
|
||||
elements->data[i] = NULL;
|
||||
}
|
||||
unsigned fieldi = 0;
|
||||
for (int i = 0; i < value.dim; i++)
|
||||
{
|
||||
Identifier *id = (Identifier *)field.data[i];
|
||||
if (id)
|
||||
{
|
||||
Dsymbol * s = ad->search(loc, id, 0);
|
||||
if (!s)
|
||||
{
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
|
||||
goto Lno;
|
||||
}
|
||||
|
||||
// Find out which field index it is
|
||||
for (fieldi = 0; 1; fieldi++)
|
||||
{
|
||||
if (fieldi >= ad->fields.dim)
|
||||
{
|
||||
s->error("is not a per-instance initializable field");
|
||||
goto Lno;
|
||||
}
|
||||
if (s == (Dsymbol *)ad->fields.data[fieldi])
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (fieldi >= ad->fields.dim)
|
||||
{ error(loc, "too many initializers for '%s'", ad->toChars());
|
||||
goto Lno;
|
||||
}
|
||||
Initializer *iz = (Initializer *)value.data[i];
|
||||
if (!iz)
|
||||
goto Lno;
|
||||
Expression *ex = iz->toExpression();
|
||||
if (!ex)
|
||||
goto Lno;
|
||||
elements->push(ex);
|
||||
if (elements->data[fieldi])
|
||||
{ error(loc, "duplicate initializer for field '%s'",
|
||||
((Dsymbol *)ad->fields.data[fieldi])->toChars());
|
||||
goto Lno;
|
||||
}
|
||||
elements->data[fieldi] = ex;
|
||||
++fieldi;
|
||||
}
|
||||
// Now, fill in any missing elements with default initializers.
|
||||
// We also need to validate any anonymous unions
|
||||
offset = 0;
|
||||
for (int i = 0; i < elements->dim; )
|
||||
{
|
||||
VarDeclaration * vd = ((Dsymbol *)ad->fields.data[i])->isVarDeclaration();
|
||||
|
||||
//printf("test2 [%d] : %s %d %d\n", i, vd->toChars(), (int)offset, (int)vd->offset);
|
||||
if (vd->offset < offset)
|
||||
{
|
||||
// Only the first field of a union can have an initializer
|
||||
if (elements->data[i])
|
||||
goto Lno;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!elements->data[i])
|
||||
// Default initialize
|
||||
elements->data[i] = vd->type->defaultInit();
|
||||
}
|
||||
offset = vd->offset + vd->type->size();
|
||||
i++;
|
||||
#if 0
|
||||
int unionSize = ad->numFieldsInUnion(i);
|
||||
if (unionSize == 1)
|
||||
{ // Not a union -- default initialize if missing
|
||||
if (!elements->data[i])
|
||||
elements->data[i] = vd->type->defaultInit();
|
||||
}
|
||||
else
|
||||
{ // anonymous union -- check for errors
|
||||
int found = -1; // index of the first field with an initializer
|
||||
for (int j = i; j < i + unionSize; ++j)
|
||||
{
|
||||
if (!elements->data[j])
|
||||
continue;
|
||||
if (found >= 0)
|
||||
{
|
||||
VarDeclaration * v1 = ((Dsymbol *)ad->fields.data[found])->isVarDeclaration();
|
||||
VarDeclaration * v = ((Dsymbol *)ad->fields.data[j])->isVarDeclaration();
|
||||
error(loc, "%s cannot have initializers for fields %s and %s in same union",
|
||||
ad->toChars(),
|
||||
v1->toChars(), v->toChars());
|
||||
goto Lno;
|
||||
}
|
||||
found = j;
|
||||
}
|
||||
if (found == -1)
|
||||
{
|
||||
error(loc, "no initializer for union that contains field %s",
|
||||
vd->toChars());
|
||||
goto Lno;
|
||||
}
|
||||
}
|
||||
i += unionSize;
|
||||
#endif
|
||||
}
|
||||
e = new StructLiteralExp(loc, sd, elements);
|
||||
e->type = sd->type;
|
||||
|
@ -274,7 +371,6 @@ Expression *StructInitializer::toExpression()
|
|||
|
||||
Lno:
|
||||
delete elements;
|
||||
//error(loc, "struct initializers as expressions are not allowed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -340,7 +436,7 @@ void ArrayInitializer::addInit(Expression *index, Initializer *value)
|
|||
type = NULL;
|
||||
}
|
||||
|
||||
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
|
||||
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
{ unsigned i;
|
||||
unsigned length;
|
||||
const unsigned amax = 0x80000000;
|
||||
|
@ -375,7 +471,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
|
|||
}
|
||||
|
||||
Initializer *val = (Initializer *)value.data[i];
|
||||
val = val->semantic(sc, t->nextOf());
|
||||
val = val->semantic(sc, t->nextOf(), needInterpret);
|
||||
value.data[i] = (void *)val;
|
||||
length++;
|
||||
if (length == 0)
|
||||
|
@ -630,12 +726,17 @@ Initializer *ExpInitializer::syntaxCopy()
|
|||
return new ExpInitializer(loc, exp->syntaxCopy());
|
||||
}
|
||||
|
||||
Initializer *ExpInitializer::semantic(Scope *sc, Type *t)
|
||||
Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
{
|
||||
//printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
|
||||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
exp = exp->optimize(WANTvalue | WANTinterpret);
|
||||
int wantOptimize = needInterpret ? WANTinterpret|WANTvalue : WANTvalue;
|
||||
|
||||
int olderrors = global.errors;
|
||||
exp = exp->optimize(wantOptimize);
|
||||
if (!global.gag && olderrors != global.errors)
|
||||
return this; // Failed, suppress duplicate error messages
|
||||
Type *tb = t->toBasetype();
|
||||
|
||||
/* Look for case of initializing a static array with a too-short
|
||||
|
@ -668,7 +769,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t)
|
|||
|
||||
exp = exp->implicitCastTo(sc, t);
|
||||
L1:
|
||||
exp = exp->optimize(WANTvalue | WANTinterpret);
|
||||
exp = exp->optimize(wantOptimize);
|
||||
//printf("-ExpInitializer::semantic(): "); exp->print();
|
||||
return this;
|
||||
}
|
||||
|
|
13
dmd2/init.h
13
dmd2/init.h
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -36,7 +36,8 @@ struct Initializer : Object
|
|||
|
||||
Initializer(Loc loc);
|
||||
virtual Initializer *syntaxCopy();
|
||||
virtual Initializer *semantic(Scope *sc, Type *t);
|
||||
// needInterpret is WANTinterpret if must be a manifest constant, 0 if not.
|
||||
virtual Initializer *semantic(Scope *sc, Type *t, int needInterpret);
|
||||
virtual Type *inferType(Scope *sc);
|
||||
virtual Expression *toExpression() = 0;
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
||||
|
@ -60,7 +61,7 @@ struct VoidInitializer : Initializer
|
|||
|
||||
VoidInitializer(Loc loc);
|
||||
Initializer *syntaxCopy();
|
||||
Initializer *semantic(Scope *sc, Type *t);
|
||||
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
|
||||
Expression *toExpression();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
|
@ -82,7 +83,7 @@ struct StructInitializer : Initializer
|
|||
StructInitializer(Loc loc);
|
||||
Initializer *syntaxCopy();
|
||||
void addInit(Identifier *field, Initializer *value);
|
||||
Initializer *semantic(Scope *sc, Type *t);
|
||||
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
|
||||
Expression *toExpression();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
|
@ -104,7 +105,7 @@ struct ArrayInitializer : Initializer
|
|||
ArrayInitializer(Loc loc);
|
||||
Initializer *syntaxCopy();
|
||||
void addInit(Expression *index, Initializer *value);
|
||||
Initializer *semantic(Scope *sc, Type *t);
|
||||
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
|
||||
int isAssociativeArray();
|
||||
Type *inferType(Scope *sc);
|
||||
Expression *toExpression();
|
||||
|
@ -125,7 +126,7 @@ struct ExpInitializer : Initializer
|
|||
|
||||
ExpInitializer(Loc loc, Expression *exp);
|
||||
Initializer *syntaxCopy();
|
||||
Initializer *semantic(Scope *sc, Type *t);
|
||||
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
|
||||
Type *inferType(Scope *sc);
|
||||
Expression *toExpression();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -257,6 +257,9 @@ int DeclarationExp::inlineCost(InlineCostState *ics)
|
|||
return COST_MAX;
|
||||
cost += 1;
|
||||
|
||||
if (vd->edtor) // if destructor required
|
||||
return COST_MAX; // needs work to make this work
|
||||
|
||||
// Scan initializer (vd->init)
|
||||
if (vd->init)
|
||||
{
|
||||
|
@ -685,7 +688,7 @@ Expression *IndexExp::doInline(InlineDoState *ids)
|
|||
ids->from.push(vd);
|
||||
ids->to.push(vto);
|
||||
|
||||
if (vd->init)
|
||||
if (vd->init && !vd->init->isVoidInitializer())
|
||||
{
|
||||
ie = vd->init->isExpInitializer();
|
||||
assert(ie);
|
||||
|
@ -724,7 +727,7 @@ Expression *SliceExp::doInline(InlineDoState *ids)
|
|||
ids->from.push(vd);
|
||||
ids->to.push(vto);
|
||||
|
||||
if (vd->init)
|
||||
if (vd->init && !vd->init->isVoidInitializer())
|
||||
{
|
||||
ie = vd->init->isExpInitializer();
|
||||
assert(ie);
|
||||
|
|
1682
dmd2/interpret.c
1682
dmd2/interpret.c
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -32,6 +32,7 @@ IRState::IRState(IRState *irs, Statement *s)
|
|||
sthis = irs->sthis;
|
||||
blx = irs->blx;
|
||||
deferToObj = irs->deferToObj;
|
||||
varsInScope = irs->varsInScope;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -41,6 +42,7 @@ IRState::IRState(IRState *irs, Statement *s)
|
|||
sthis = NULL;
|
||||
blx = NULL;
|
||||
deferToObj = NULL;
|
||||
varsInScope = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,6 +66,7 @@ IRState::IRState(IRState *irs, Dsymbol *s)
|
|||
sthis = irs->sthis;
|
||||
blx = irs->blx;
|
||||
deferToObj = irs->deferToObj;
|
||||
varsInScope = irs->varsInScope;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -73,6 +76,7 @@ IRState::IRState(IRState *irs, Dsymbol *s)
|
|||
sthis = NULL;
|
||||
blx = NULL;
|
||||
deferToObj = NULL;
|
||||
varsInScope = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,6 +98,7 @@ IRState::IRState(Module *m, Dsymbol *s)
|
|||
blx = NULL;
|
||||
deferToObj = NULL;
|
||||
startaddress = NULL;
|
||||
varsInScope = NULL;
|
||||
}
|
||||
|
||||
block *IRState::getBreakBlock(Identifier *ident)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -37,6 +37,7 @@ struct IRState
|
|||
Array *deferToObj; // array of Dsymbol's to run toObjFile(int multiobj) on later
|
||||
elem *ehidden; // transmit hidden pointer to CallExp::toElem()
|
||||
Symbol *startaddress;
|
||||
Array *varsInScope; // variables that are in scope that will need destruction later
|
||||
|
||||
block *breakBlock;
|
||||
block *contBlock;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -2261,6 +2261,7 @@ done:
|
|||
}
|
||||
|
||||
// Parse trailing 'u', 'U', 'l' or 'L' in any combination
|
||||
const unsigned char *psuffix = p;
|
||||
while (1)
|
||||
{ unsigned char f;
|
||||
|
||||
|
@ -2287,6 +2288,10 @@ done:
|
|||
break;
|
||||
}
|
||||
|
||||
if (state == STATE_octal && n >= 8 && !global.params.useDeprecated)
|
||||
error("octal literals 0%llo%.*s are deprecated, use std.conv.octal!%llo%.*s instead",
|
||||
n, p - psuffix, psuffix, n, p - psuffix, psuffix);
|
||||
|
||||
switch (flags)
|
||||
{
|
||||
case 0:
|
||||
|
|
|
@ -100,7 +100,7 @@ Global::Global()
|
|||
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
|
||||
#endif
|
||||
;
|
||||
version = "v2.052";
|
||||
version = "v2.053";
|
||||
#if IN_LLVM
|
||||
ldc_version = "LDC trunk";
|
||||
llvm_version = "LLVM 2.9";
|
||||
|
@ -182,7 +182,7 @@ void verror(Loc loc, const char *format, va_list ap)
|
|||
#endif
|
||||
fprintf(stdmsg, "\n");
|
||||
fflush(stdmsg);
|
||||
//halt();
|
||||
halt();
|
||||
}
|
||||
global.errors++;
|
||||
}
|
||||
|
|
80
dmd2/mtype.c
80
dmd2/mtype.c
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -1666,6 +1666,15 @@ int Type::checkBoolean()
|
|||
return isscalar();
|
||||
}
|
||||
|
||||
/********************************
|
||||
* TRUE if when type goes out of scope, it needs a destructor applied.
|
||||
* Only applies to value types, not ref types.
|
||||
*/
|
||||
int Type::needsDestruction()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* Check type to see if it is based on a deprecated symbol.
|
||||
*/
|
||||
|
@ -2067,6 +2076,7 @@ Expression *Type::toExpression()
|
|||
|
||||
int Type::hasPointers()
|
||||
{
|
||||
//printf("Type::hasPointers() %s, %d\n", toChars(), ty);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -3416,7 +3426,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
|
|||
sc = sc->pop();
|
||||
|
||||
if (d >= td->objects->dim)
|
||||
{ error(loc, "tuple index %ju exceeds %u", d, td->objects->dim);
|
||||
{ error(loc, "tuple index %ju exceeds length %u", d, td->objects->dim);
|
||||
goto Ldefault;
|
||||
}
|
||||
Object *o = (Object *)td->objects->data[(size_t)d];
|
||||
|
@ -3492,7 +3502,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
|||
|
||||
dim = semanticLength(sc, tbn, dim);
|
||||
|
||||
dim = dim->optimize(WANTvalue | WANTinterpret);
|
||||
dim = dim->optimize(WANTvalue);
|
||||
if (sc && sc->parameterSpecialization && dim->op == TOKvar &&
|
||||
((VarExp *)dim)->var->storage_class & STCtemplateparameter)
|
||||
{
|
||||
|
@ -3501,6 +3511,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
|||
*/
|
||||
return this;
|
||||
}
|
||||
dim = dim->optimize(WANTvalue | WANTinterpret);
|
||||
dinteger_t d1 = dim->toInteger();
|
||||
dim = dim->implicitCastTo(sc, tsize_t);
|
||||
dim = dim->optimize(WANTvalue);
|
||||
|
@ -3551,8 +3562,8 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
|||
}
|
||||
case Tstruct:
|
||||
{ TypeStruct *ts = (TypeStruct *)tbn;
|
||||
if (ts->sym->isnested)
|
||||
{ error(loc, "cannot have array of inner structs %s", ts->toChars());
|
||||
if (0 && ts->sym->isnested)
|
||||
{ error(loc, "cannot have static array of inner struct %s", ts->toChars());
|
||||
goto Lerror;
|
||||
}
|
||||
break;
|
||||
|
@ -3717,6 +3728,11 @@ int TypeSArray::isZeroInit(Loc loc)
|
|||
return next->isZeroInit(loc);
|
||||
}
|
||||
|
||||
int TypeSArray::needsDestruction()
|
||||
{
|
||||
return next->needsDestruction();
|
||||
}
|
||||
|
||||
Expression *TypeSArray::defaultInitLiteral(Loc loc)
|
||||
{
|
||||
#if LOGDEFAULTINIT
|
||||
|
@ -3746,7 +3762,18 @@ Expression *TypeSArray::toExpression()
|
|||
|
||||
int TypeSArray::hasPointers()
|
||||
{
|
||||
return next->hasPointers();
|
||||
/* Don't want to do this, because:
|
||||
* struct S { T* array[0]; }
|
||||
* may be a variable length struct.
|
||||
*/
|
||||
//if (dim->toInteger() == 0)
|
||||
//return FALSE;
|
||||
|
||||
if (next->ty == Tvoid)
|
||||
// Arrays of void contain arbitrary data, which may include pointers
|
||||
return TRUE;
|
||||
else
|
||||
return next->hasPointers();
|
||||
}
|
||||
|
||||
/***************************** TypeDArray *****************************/
|
||||
|
@ -3797,8 +3824,8 @@ Type *TypeDArray::semantic(Loc loc, Scope *sc)
|
|||
break;
|
||||
case Tstruct:
|
||||
{ TypeStruct *ts = (TypeStruct *)tbn;
|
||||
if (ts->sym->isnested)
|
||||
error(loc, "cannot have array of inner structs %s", ts->toChars());
|
||||
if (0 && ts->sym->isnested)
|
||||
error(loc, "cannot have dynamic array of inner struct %s", ts->toChars());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4000,7 +4027,7 @@ Type *TypeNewArray::semantic(Loc loc, Scope *sc)
|
|||
break;
|
||||
case Tstruct:
|
||||
{ TypeStruct *ts = (TypeStruct *)tbn;
|
||||
if (ts->sym->isnested)
|
||||
if (0 && ts->sym->isnested)
|
||||
error(loc, "cannot have array of inner structs %s", ts->toChars());
|
||||
break;
|
||||
}
|
||||
|
@ -5584,6 +5611,16 @@ Type *TypeDelegate::semantic(Loc loc, Scope *sc)
|
|||
return this;
|
||||
}
|
||||
next = next->semantic(loc,sc);
|
||||
/* In order to deal with Bugzilla 4028, perhaps default arguments should
|
||||
* be removed from next before the merge.
|
||||
*/
|
||||
|
||||
/* Don't return merge(), because arg identifiers and default args
|
||||
* can be different
|
||||
* even though the types match
|
||||
*/
|
||||
//deco = merge()->deco;
|
||||
//return this;
|
||||
return merge();
|
||||
}
|
||||
|
||||
|
@ -5829,8 +5866,11 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
|
|||
*pe = e;
|
||||
}
|
||||
else
|
||||
{
|
||||
Lerror:
|
||||
error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
|
||||
*pe = new ErrorExp();
|
||||
}
|
||||
return;
|
||||
}
|
||||
L2:
|
||||
|
@ -5929,6 +5969,7 @@ L1:
|
|||
else
|
||||
error(loc, "undefined identifier %s", p);
|
||||
}
|
||||
*pt = Type::terror;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6657,6 +6698,11 @@ int TypeEnum::checkBoolean()
|
|||
return sym->memtype->checkBoolean();
|
||||
}
|
||||
|
||||
int TypeEnum::needsDestruction()
|
||||
{
|
||||
return sym->memtype->needsDestruction();
|
||||
}
|
||||
|
||||
MATCH TypeEnum::implicitConvTo(Type *to)
|
||||
{ MATCH m;
|
||||
|
||||
|
@ -6860,6 +6906,11 @@ int TypeTypedef::checkBoolean()
|
|||
return sym->basetype->checkBoolean();
|
||||
}
|
||||
|
||||
int TypeTypedef::needsDestruction()
|
||||
{
|
||||
return sym->basetype->needsDestruction();
|
||||
}
|
||||
|
||||
Type *TypeTypedef::toBasetype()
|
||||
{
|
||||
if (sym->inuse)
|
||||
|
@ -7295,7 +7346,11 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
|
|||
VarDeclaration *vd = (VarDeclaration *)(sym->fields.data[j]);
|
||||
Expression *e;
|
||||
if (vd->init)
|
||||
e = vd->init->toExpression();
|
||||
{ if (vd->init->isVoidInitializer())
|
||||
e = NULL;
|
||||
else
|
||||
e = vd->init->toExpression();
|
||||
}
|
||||
else
|
||||
e = vd->type->defaultInitLiteral();
|
||||
structelems->data[j] = e;
|
||||
|
@ -7318,6 +7373,11 @@ int TypeStruct::checkBoolean()
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
int TypeStruct::needsDestruction()
|
||||
{
|
||||
return sym->dtor != NULL;
|
||||
}
|
||||
|
||||
int TypeStruct::isAssignable()
|
||||
{
|
||||
/* If any of the fields are const or invariant,
|
||||
|
|
|
@ -334,6 +334,7 @@ struct Type : Object
|
|||
virtual TypeTuple *toArgTypes();
|
||||
virtual Type *nextOf();
|
||||
uinteger_t sizemask();
|
||||
virtual int needsDestruction();
|
||||
|
||||
|
||||
static void error(Loc loc, const char *format, ...) IS_PRINTF(2);
|
||||
|
@ -463,6 +464,7 @@ struct TypeSArray : TypeArray
|
|||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
Expression *toExpression();
|
||||
int hasPointers();
|
||||
int needsDestruction();
|
||||
TypeTuple *toArgTypes();
|
||||
#if CPP_MANGLE
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
|
@ -772,6 +774,7 @@ struct TypeStruct : Type
|
|||
int isZeroInit(Loc loc);
|
||||
int isAssignable();
|
||||
int checkBoolean();
|
||||
int needsDestruction();
|
||||
#if IN_DMD
|
||||
dt_t **toDt(dt_t **pdt);
|
||||
#endif
|
||||
|
@ -820,6 +823,7 @@ struct TypeEnum : Type
|
|||
int isunsigned();
|
||||
int checkBoolean();
|
||||
int isAssignable();
|
||||
int needsDestruction();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
MATCH constConv(Type *to);
|
||||
Type *toBasetype();
|
||||
|
@ -863,6 +867,7 @@ struct TypeTypedef : Type
|
|||
int isunsigned();
|
||||
int checkBoolean();
|
||||
int isAssignable();
|
||||
int needsDestruction();
|
||||
Type *toBasetype();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
MATCH constConv(Type *to);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -57,11 +57,11 @@ Expression *expandVar(int result, VarDeclaration *v)
|
|||
//error("ICE");
|
||||
return e;
|
||||
}
|
||||
|
||||
Type *tb = v->type->toBasetype();
|
||||
if (result & WANTinterpret ||
|
||||
v->storage_class & STCmanifest ||
|
||||
(tb->ty != Tsarray && tb->ty != Tstruct)
|
||||
v->type->toBasetype()->isscalar() ||
|
||||
((result & WANTexpand) && (tb->ty != Tsarray && tb->ty != Tstruct))
|
||||
)
|
||||
{
|
||||
if (v->init)
|
||||
|
@ -73,13 +73,31 @@ Expression *expandVar(int result, VarDeclaration *v)
|
|||
}
|
||||
Expression *ei = v->init->toExpression();
|
||||
if (!ei)
|
||||
{ if (v->storage_class & STCmanifest)
|
||||
v->error("enum cannot be initialized with %s", v->init->toChars());
|
||||
goto L1;
|
||||
}
|
||||
if (ei->op == TOKconstruct || ei->op == TOKblit)
|
||||
{ AssignExp *ae = (AssignExp *)ei;
|
||||
ei = ae->e2;
|
||||
if (ei->isConst() != 1 && ei->op != TOKstring)
|
||||
if (result & WANTinterpret)
|
||||
{
|
||||
v->inuse++;
|
||||
ei = ei->optimize(result);
|
||||
v->inuse--;
|
||||
}
|
||||
else if (ei->isConst() != 1 && ei->op != TOKstring)
|
||||
goto L1;
|
||||
if (ei->type != v->type)
|
||||
|
||||
if (ei->type == v->type)
|
||||
{ // const variable initialized with const expression
|
||||
}
|
||||
else if (ei->implicitConvTo(v->type) >= MATCHconst)
|
||||
{ // const var initialized with non-const expression
|
||||
ei = ei->implicitCastTo(0, v->type);
|
||||
ei = ei->semantic(0);
|
||||
}
|
||||
else
|
||||
goto L1;
|
||||
}
|
||||
if (v->scope)
|
||||
|
@ -154,7 +172,17 @@ Expression *fromConstInitializer(int result, Expression *e1)
|
|||
e->loc = e1->loc;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = e1;
|
||||
/* If we needed to interpret, generate an error.
|
||||
* Don't give an error if it's a template parameter
|
||||
*/
|
||||
if (v && (result & WANTinterpret) &&
|
||||
!(v->storage_class & STCtemplateparameter))
|
||||
{
|
||||
e1->error("variable %s cannot be read at compile time", v->toChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
@ -189,7 +217,7 @@ Expression *ArrayLiteralExp::optimize(int result)
|
|||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = (Expression *)elements->data[i];
|
||||
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
elements->data[i] = (void *)e;
|
||||
}
|
||||
}
|
||||
|
@ -202,11 +230,11 @@ Expression *AssocArrayLiteralExp::optimize(int result)
|
|||
for (size_t i = 0; i < keys->dim; i++)
|
||||
{ Expression *e = (Expression *)keys->data[i];
|
||||
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
keys->data[i] = (void *)e;
|
||||
|
||||
e = (Expression *)values->data[i];
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
values->data[i] = (void *)e;
|
||||
}
|
||||
return this;
|
||||
|
@ -220,7 +248,7 @@ Expression *StructLiteralExp::optimize(int result)
|
|||
{ Expression *e = (Expression *)elements->data[i];
|
||||
if (!e)
|
||||
continue;
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
elements->data[i] = (void *)e;
|
||||
}
|
||||
}
|
||||
|
@ -460,6 +488,10 @@ Expression *NewExp::optimize(int result)
|
|||
arguments->data[i] = (void *)e;
|
||||
}
|
||||
}
|
||||
if (result & WANTinterpret)
|
||||
{
|
||||
error("cannot evaluate %s at compile time", toChars());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -851,7 +883,7 @@ Expression *ArrayLengthExp::optimize(int result)
|
|||
{ Expression *e;
|
||||
|
||||
//printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e1 = e1->optimize(WANTvalue | WANTexpand | (result & WANTinterpret));
|
||||
e = this;
|
||||
if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
|
||||
{
|
||||
|
@ -894,11 +926,36 @@ Expression *IdentityExp::optimize(int result)
|
|||
return e;
|
||||
}
|
||||
|
||||
/* It is possible for constant folding to change an array expression of
|
||||
* unknown length, into one where the length is known.
|
||||
* If the expression 'arr' is a literal, set lengthVar to be its length.
|
||||
*/
|
||||
void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr)
|
||||
{
|
||||
if (!lengthVar)
|
||||
return;
|
||||
if (lengthVar->init && !lengthVar->init->isVoidInitializer())
|
||||
return; // we have previously calculated the length
|
||||
size_t len;
|
||||
if (arr->op == TOKstring)
|
||||
len = ((StringExp *)arr)->len;
|
||||
else if (arr->op == TOKarrayliteral)
|
||||
len = ((ArrayLiteralExp *)arr)->elements->dim;
|
||||
else
|
||||
return; // we don't know the length yet
|
||||
|
||||
Expression *dollar = new IntegerExp(0, len, Type::tsize_t);
|
||||
lengthVar->init = new ExpInitializer(0, dollar);
|
||||
lengthVar->storage_class |= STCstatic | STCconst;
|
||||
}
|
||||
|
||||
|
||||
Expression *IndexExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
|
||||
Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
Expression *e1 = this->e1->optimize(
|
||||
WANTvalue | (result & (WANTinterpret| WANTexpand)));
|
||||
e1 = fromConstInitializer(result, e1);
|
||||
if (this->e1->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)this->e1;
|
||||
|
@ -910,6 +967,8 @@ Expression *IndexExp::optimize(int result)
|
|||
this->e1 = e1;
|
||||
}
|
||||
}
|
||||
// We might know $ now
|
||||
setLengthVarIfKnown(lengthVar, e1);
|
||||
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = Index(type, e1, e2);
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
|
@ -917,12 +976,13 @@ Expression *IndexExp::optimize(int result)
|
|||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expression *SliceExp::optimize(int result)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e = this;
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e1 = e1->optimize(WANTvalue | (result & (WANTinterpret|WANTexpand)));
|
||||
if (!lwr)
|
||||
{ if (e1->op == TOKstring)
|
||||
{ // Convert slice of string literal into dynamic array
|
||||
|
@ -933,6 +993,8 @@ Expression *SliceExp::optimize(int result)
|
|||
return e;
|
||||
}
|
||||
e1 = fromConstInitializer(result, e1);
|
||||
// We might know $ now
|
||||
setLengthVarIfKnown(lengthVar, e1);
|
||||
lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
|
||||
upr = upr->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = Slice(type, e1, lwr, upr);
|
||||
|
|
32
dmd2/parse.c
32
dmd2/parse.c
|
@ -485,10 +485,10 @@ Dsymbols *Parser::parseDeclDefs(int once)
|
|||
if (token.value == TOKlparen)
|
||||
{
|
||||
nextToken();
|
||||
if (token.value == TOKint32v)
|
||||
if (token.value == TOKint32v && token.uns64value > 0)
|
||||
n = (unsigned)token.uns64value;
|
||||
else
|
||||
{ error("integer expected, not %s", token.toChars());
|
||||
{ error("positive integer expected, not %s", token.toChars());
|
||||
n = 1;
|
||||
}
|
||||
nextToken();
|
||||
|
@ -3447,7 +3447,7 @@ Statement *Parser::parseStatement(int flags)
|
|||
nextToken();
|
||||
Dsymbols *a = parseBlock();
|
||||
Dsymbol *d = new StorageClassDeclaration(STCstatic, a);
|
||||
s = new DeclarationStatement(loc, d);
|
||||
s = new ExpStatement(loc, d);
|
||||
if (flags & PSscope)
|
||||
s = new ScopeStatement(loc, s);
|
||||
break;
|
||||
|
@ -3493,7 +3493,7 @@ Statement *Parser::parseStatement(int flags)
|
|||
for (int i = 0; i < a->dim; i++)
|
||||
{
|
||||
Dsymbol *d = (Dsymbol *)a->data[i];
|
||||
s = new DeclarationStatement(loc, d);
|
||||
s = new ExpStatement(loc, d);
|
||||
as->push(s);
|
||||
}
|
||||
s = new CompoundDeclarationStatement(loc, as);
|
||||
|
@ -3501,7 +3501,7 @@ Statement *Parser::parseStatement(int flags)
|
|||
else if (a->dim == 1)
|
||||
{
|
||||
Dsymbol *d = (Dsymbol *)a->data[0];
|
||||
s = new DeclarationStatement(loc, d);
|
||||
s = new ExpStatement(loc, d);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
|
@ -3517,7 +3517,7 @@ Statement *Parser::parseStatement(int flags)
|
|||
{ Dsymbol *d;
|
||||
|
||||
d = parseAggregate();
|
||||
s = new DeclarationStatement(loc, d);
|
||||
s = new ExpStatement(loc, d);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3540,7 +3540,7 @@ Statement *Parser::parseStatement(int flags)
|
|||
else
|
||||
goto Ldeclaration;
|
||||
}
|
||||
s = new DeclarationStatement(loc, d);
|
||||
s = new ExpStatement(loc, d);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3548,16 +3548,21 @@ Statement *Parser::parseStatement(int flags)
|
|||
{ t = peek(&token);
|
||||
if (t->value == TOKlparen)
|
||||
{ // mixin(string)
|
||||
nextToken();
|
||||
check(TOKlparen, "mixin");
|
||||
Expression *e = parseAssignExp();
|
||||
check(TOKrparen);
|
||||
check(TOKsemicolon);
|
||||
s = new CompileStatement(loc, e);
|
||||
if (e->op == TOKmixin)
|
||||
{
|
||||
CompileExp *cpe = (CompileExp *)e;
|
||||
s = new CompileStatement(loc, cpe->e1);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = new ExpStatement(loc, e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Dsymbol *d = parseMixin();
|
||||
s = new DeclarationStatement(loc, d);
|
||||
s = new ExpStatement(loc, d);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3596,7 +3601,7 @@ Statement *Parser::parseStatement(int flags)
|
|||
if (!(flags & PSsemi))
|
||||
error("use '{ }' for an empty statement, not a ';'");
|
||||
nextToken();
|
||||
s = new ExpStatement(loc, NULL);
|
||||
s = new ExpStatement(loc, (Expression *)NULL);
|
||||
break;
|
||||
|
||||
case TOKdo:
|
||||
|
@ -5435,6 +5440,7 @@ Expression *Parser::parsePostExp(Expression *e)
|
|||
nextToken();
|
||||
if (token.value == TOKrbracket)
|
||||
{ // array[]
|
||||
inBrackets--;
|
||||
e = new SliceExp(loc, e, NULL, NULL);
|
||||
nextToken();
|
||||
}
|
||||
|
|
|
@ -94,6 +94,8 @@ struct Scope
|
|||
#define SCOPEctor 1 // constructor type
|
||||
#define SCOPEstaticif 2 // inside static if
|
||||
#define SCOPEfree 4 // is on free list
|
||||
#define SCOPEstaticassert 8 // inside static assert
|
||||
#define SCOPEdebug 0x10 // inside debug conditional
|
||||
|
||||
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
|
||||
|
||||
|
|
338
dmd2/statement.c
338
dmd2/statement.c
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -188,13 +188,14 @@ int Statement::isEmpty()
|
|||
* *sfinally code executed in finally block
|
||||
*/
|
||||
|
||||
void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
|
||||
Statement *Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
|
||||
{
|
||||
//printf("Statement::scopeCode()\n");
|
||||
//print();
|
||||
*sentry = NULL;
|
||||
*sexception = NULL;
|
||||
*sfinally = NULL;
|
||||
return this;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
|
@ -233,6 +234,12 @@ ExpStatement::ExpStatement(Loc loc, Expression *exp)
|
|||
this->exp = exp;
|
||||
}
|
||||
|
||||
ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration)
|
||||
: Statement(loc)
|
||||
{
|
||||
this->exp = new DeclarationExp(loc, declaration);
|
||||
}
|
||||
|
||||
Statement *ExpStatement::syntaxCopy()
|
||||
{
|
||||
Expression *e = exp ? exp->syntaxCopy() : NULL;
|
||||
|
@ -243,10 +250,19 @@ Statement *ExpStatement::syntaxCopy()
|
|||
void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (exp)
|
||||
exp->toCBuffer(buf, hgs);
|
||||
buf->writeByte(';');
|
||||
if (!hgs->FLinit.init)
|
||||
buf->writenl();
|
||||
{ exp->toCBuffer(buf, hgs);
|
||||
if (exp->op != TOKdeclaration)
|
||||
{ buf->writeByte(';');
|
||||
if (!hgs->FLinit.init)
|
||||
buf->writenl();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf->writeByte(';');
|
||||
if (!hgs->FLinit.init)
|
||||
buf->writenl();
|
||||
}
|
||||
}
|
||||
|
||||
Statement *ExpStatement::semantic(Scope *sc)
|
||||
|
@ -271,14 +287,10 @@ Statement *ExpStatement::semantic(Scope *sc)
|
|||
#endif
|
||||
|
||||
exp = exp->semantic(sc);
|
||||
exp = exp->addDtorHook(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
exp->checkSideEffect(0);
|
||||
exp = exp->optimize(0);
|
||||
if (exp->op == TOKdeclaration && !isDeclarationStatement())
|
||||
{ Statement *s = new DeclarationStatement(loc, exp);
|
||||
return s;
|
||||
}
|
||||
//exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -307,6 +319,55 @@ int ExpStatement::isEmpty()
|
|||
return exp == NULL;
|
||||
}
|
||||
|
||||
Statement *ExpStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
|
||||
{
|
||||
//printf("ExpStatement::scopeCode()\n");
|
||||
//print();
|
||||
|
||||
*sentry = NULL;
|
||||
*sexception = NULL;
|
||||
*sfinally = NULL;
|
||||
|
||||
if (exp)
|
||||
{
|
||||
if (exp->op == TOKdeclaration)
|
||||
{
|
||||
DeclarationExp *de = (DeclarationExp *)(exp);
|
||||
VarDeclaration *v = de->declaration->isVarDeclaration();
|
||||
if (v && !v->noscope)
|
||||
{
|
||||
Expression *e = v->edtor;
|
||||
if (e)
|
||||
{
|
||||
//printf("dtor is: "); e->print();
|
||||
#if 0
|
||||
if (v->type->toBasetype()->ty == Tstruct)
|
||||
{ /* Need a 'gate' to turn on/off destruction,
|
||||
* in case v gets moved elsewhere.
|
||||
*/
|
||||
Identifier *id = Lexer::uniqueId("__runDtor");
|
||||
ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1));
|
||||
VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie);
|
||||
*sentry = new ExpStatement(loc, rd);
|
||||
v->rundtor = rd;
|
||||
|
||||
/* Rewrite e as:
|
||||
* rundtor && e
|
||||
*/
|
||||
Expression *ve = new VarExp(loc, v->rundtor);
|
||||
e = new AndAndExp(loc, ve, e);
|
||||
e->type = Type::tbool;
|
||||
}
|
||||
#endif
|
||||
*sfinally = new ExpStatement(loc, e);
|
||||
}
|
||||
v->noscope = 1; // don't add in dtor again
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/******************************** CompileStatement ***************************/
|
||||
|
||||
|
@ -338,6 +399,8 @@ Statements *CompileStatement::flatten(Scope *sc)
|
|||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
exp = exp->optimize(WANTvalue | WANTinterpret);
|
||||
if (exp->op == TOKerror)
|
||||
return NULL;
|
||||
if (exp->op != TOKstring)
|
||||
{ error("argument to mixin must be a string, not (%s)", exp->toChars());
|
||||
return NULL;
|
||||
|
@ -369,78 +432,6 @@ Statement *CompileStatement::semantic(Scope *sc)
|
|||
}
|
||||
|
||||
|
||||
/******************************** DeclarationStatement ***************************/
|
||||
|
||||
DeclarationStatement::DeclarationStatement(Loc loc, Dsymbol *declaration)
|
||||
: ExpStatement(loc, new DeclarationExp(loc, declaration))
|
||||
{
|
||||
}
|
||||
|
||||
DeclarationStatement::DeclarationStatement(Loc loc, Expression *exp)
|
||||
: ExpStatement(loc, exp)
|
||||
{
|
||||
}
|
||||
|
||||
Statement *DeclarationStatement::syntaxCopy()
|
||||
{
|
||||
DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy());
|
||||
return ds;
|
||||
}
|
||||
|
||||
void DeclarationStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
|
||||
{
|
||||
//printf("DeclarationStatement::scopeCode()\n");
|
||||
//print();
|
||||
|
||||
*sentry = NULL;
|
||||
*sexception = NULL;
|
||||
*sfinally = NULL;
|
||||
|
||||
if (exp)
|
||||
{
|
||||
if (exp->op == TOKdeclaration)
|
||||
{
|
||||
DeclarationExp *de = (DeclarationExp *)(exp);
|
||||
VarDeclaration *v = de->declaration->isVarDeclaration();
|
||||
if (v)
|
||||
{ Expression *e;
|
||||
|
||||
e = v->callScopeDtor(sc);
|
||||
if (e)
|
||||
{
|
||||
//printf("dtor is: "); e->print();
|
||||
#if 0
|
||||
if (v->type->toBasetype()->ty == Tstruct)
|
||||
{ /* Need a 'gate' to turn on/off destruction,
|
||||
* in case v gets moved elsewhere.
|
||||
*/
|
||||
Identifier *id = Lexer::uniqueId("__runDtor");
|
||||
ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1));
|
||||
VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie);
|
||||
*sentry = new DeclarationStatement(loc, rd);
|
||||
v->rundtor = rd;
|
||||
|
||||
/* Rewrite e as:
|
||||
* rundtor && e
|
||||
*/
|
||||
Expression *ve = new VarExp(loc, v->rundtor);
|
||||
e = new AndAndExp(loc, ve, e);
|
||||
e->type = Type::tbool;
|
||||
}
|
||||
#endif
|
||||
*sfinally = new ExpStatement(loc, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
exp->toCBuffer(buf, hgs);
|
||||
}
|
||||
|
||||
|
||||
/******************************** CompoundStatement ***************************/
|
||||
|
||||
CompoundStatement::CompoundStatement(Loc loc, Statements *s)
|
||||
|
@ -485,6 +476,15 @@ Statement *CompoundStatement::semantic(Scope *sc)
|
|||
|
||||
//printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
|
||||
|
||||
#if 0
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{
|
||||
s = (Statement *) statements->data[i];
|
||||
if (s)
|
||||
printf("[%d]: %s", i, s->toChars());
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < statements->dim; )
|
||||
{
|
||||
s = (Statement *) statements->data[i];
|
||||
|
@ -505,29 +505,18 @@ Statement *CompoundStatement::semantic(Scope *sc)
|
|||
Statement *sexception;
|
||||
Statement *sfinally;
|
||||
|
||||
s->scopeCode(sc, &sentry, &sexception, &sfinally);
|
||||
statements->data[i] = s->scopeCode(sc, &sentry, &sexception, &sfinally);
|
||||
if (sentry)
|
||||
{
|
||||
sentry = sentry->semantic(sc);
|
||||
if (s->isDeclarationStatement())
|
||||
{ statements->insert(i, sentry);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
statements->data[i] = sentry;
|
||||
statements->insert(i, sentry);
|
||||
i++;
|
||||
}
|
||||
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
|
||||
{
|
||||
|
@ -724,11 +713,12 @@ void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||
int nwritten = 0;
|
||||
for (int i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
if (s)
|
||||
{ DeclarationStatement *ds = s->isDeclarationStatement();
|
||||
assert(ds);
|
||||
ExpStatement *ds;
|
||||
if (s &&
|
||||
(ds = s->isExpStatement()) != NULL &&
|
||||
ds->exp->op == TOKdeclaration)
|
||||
{
|
||||
DeclarationExp *de = (DeclarationExp *)ds->exp;
|
||||
assert(de->op == TOKdeclaration);
|
||||
Declaration *d = de->declaration->isDeclaration();
|
||||
assert(d);
|
||||
VarDeclaration *v = d->isVarDeclaration();
|
||||
|
@ -931,7 +921,9 @@ Statement *ScopeStatement::semantic(Scope *sc)
|
|||
Statement *sexception;
|
||||
Statement *sfinally;
|
||||
|
||||
statement->scopeCode(sc, &sentry, &sexception, &sfinally);
|
||||
statement = statement->scopeCode(sc, &sentry, &sexception, &sfinally);
|
||||
assert(!sentry);
|
||||
assert(!sexception);
|
||||
if (sfinally)
|
||||
{
|
||||
//printf("adding sfinally\n");
|
||||
|
@ -1228,14 +1220,15 @@ Statement *ForStatement::semantic(Scope *sc)
|
|||
return this;
|
||||
}
|
||||
|
||||
void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
|
||||
Statement *ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
|
||||
{
|
||||
//printf("ForStatement::scopeCode()\n");
|
||||
//print();
|
||||
if (init)
|
||||
init->scopeCode(sc, sentry, sexception, sfinally);
|
||||
init = init->scopeCode(sc, sentry, sexception, sfinally);
|
||||
else
|
||||
Statement::scopeCode(sc, sentry, sexception, sfinally);
|
||||
return this;
|
||||
}
|
||||
|
||||
int ForStatement::hasBreak()
|
||||
|
@ -1592,8 +1585,8 @@ Lagain:
|
|||
key->init = new ExpInitializer(loc, new IntegerExp(0));
|
||||
|
||||
Statements *cs = new Statements();
|
||||
cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
|
||||
cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
|
||||
cs->push(new ExpStatement(loc, tmp));
|
||||
cs->push(new ExpStatement(loc, key));
|
||||
Statement *forinit = new CompoundDeclarationStatement(loc, cs);
|
||||
|
||||
Expression *cond;
|
||||
|
@ -1611,7 +1604,7 @@ Lagain:
|
|||
|
||||
// T value = tmp[key];
|
||||
value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key)));
|
||||
Statement *ds = new DeclarationStatement(loc, new DeclarationExp(loc, value));
|
||||
Statement *ds = new ExpStatement(loc, value);
|
||||
|
||||
body = new CompoundStatement(loc, ds, body);
|
||||
|
||||
|
@ -1722,7 +1715,7 @@ Lagain:
|
|||
VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit));
|
||||
// r->semantic(sc);
|
||||
//printf("r: %s, init: %s\n", r->toChars(), r->init->toChars());
|
||||
Statement *init = new DeclarationStatement(loc, r);
|
||||
Statement *init = new ExpStatement(loc, r);
|
||||
//printf("init: %s\n", init->toChars());
|
||||
|
||||
// !__r.empty
|
||||
|
@ -1748,7 +1741,7 @@ Lagain:
|
|||
DeclarationExp *de = new DeclarationExp(loc, ve);
|
||||
|
||||
Statement *body = new CompoundStatement(loc,
|
||||
new DeclarationStatement(loc, de), this->body);
|
||||
new ExpStatement(loc, de), this->body);
|
||||
|
||||
s = new ForStatement(loc, init, condition, increment, body);
|
||||
#if 0
|
||||
|
@ -1809,7 +1802,7 @@ Lagain:
|
|||
id = Lexer::uniqueId("__applyArg", i);
|
||||
Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id));
|
||||
VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie);
|
||||
s = new DeclarationStatement(0, v);
|
||||
s = new ExpStatement(0, v);
|
||||
body = new CompoundStatement(loc, s, body);
|
||||
}
|
||||
a = new Parameter(STCref, arg->type, id, NULL);
|
||||
|
@ -2051,6 +2044,9 @@ Lagain:
|
|||
}
|
||||
break;
|
||||
}
|
||||
case Terror:
|
||||
s = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
error("foreach: %s is not an aggregate type", aggr->type->toChars());
|
||||
|
@ -2239,13 +2235,13 @@ Statement *ForeachRangeStatement::semantic(Scope *sc)
|
|||
// Keep order of evaluation as lwr, then upr
|
||||
if (op == TOKforeach)
|
||||
{
|
||||
cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
|
||||
cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
|
||||
cs->push(new ExpStatement(loc, key));
|
||||
cs->push(new ExpStatement(loc, tmp));
|
||||
}
|
||||
else
|
||||
{
|
||||
cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
|
||||
cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
|
||||
cs->push(new ExpStatement(loc, tmp));
|
||||
cs->push(new ExpStatement(loc, key));
|
||||
}
|
||||
Statement *forinit = new CompoundDeclarationStatement(loc, cs);
|
||||
|
||||
|
@ -2554,7 +2550,16 @@ Statement *ConditionalStatement::semantic(Scope *sc)
|
|||
// This feature allows a limited form of conditional compilation.
|
||||
if (condition->include(sc, NULL))
|
||||
{
|
||||
ifbody = ifbody->semantic(sc);
|
||||
DebugCondition *dc = condition->isDebugCondition();
|
||||
if (dc)
|
||||
{
|
||||
sc = sc->push();
|
||||
sc->flags |= SCOPEdebug;
|
||||
ifbody = ifbody->semantic(sc);
|
||||
sc->pop();
|
||||
}
|
||||
else
|
||||
ifbody = ifbody->semantic(sc);
|
||||
return ifbody;
|
||||
}
|
||||
else
|
||||
|
@ -2569,8 +2574,15 @@ Statements *ConditionalStatement::flatten(Scope *sc)
|
|||
{
|
||||
Statement *s;
|
||||
|
||||
//printf("ConditionalStatement::flatten()\n");
|
||||
if (condition->include(sc, NULL))
|
||||
s = ifbody;
|
||||
{
|
||||
DebugCondition *dc = condition->isDebugCondition();
|
||||
if (dc)
|
||||
s = new DebugStatement(loc, ifbody);
|
||||
else
|
||||
s = ifbody;
|
||||
}
|
||||
else
|
||||
s = elsebody;
|
||||
|
||||
|
@ -3051,7 +3063,7 @@ Statement *CaseStatement::semantic(Scope *sc)
|
|||
}
|
||||
#endif
|
||||
exp = exp->implicitCastTo(sc, sw->condition->type);
|
||||
exp = exp->optimize(WANTvalue | WANTinterpret);
|
||||
exp = exp->optimize(WANTvalue);
|
||||
|
||||
/* This is where variables are allowed as case expressions.
|
||||
*/
|
||||
|
@ -3069,8 +3081,10 @@ Statement *CaseStatement::semantic(Scope *sc)
|
|||
goto L1;
|
||||
}
|
||||
}
|
||||
else
|
||||
exp = exp->optimize(WANTvalue | WANTinterpret);
|
||||
|
||||
if (exp->op != TOKstring && exp->op != TOKint64)
|
||||
if (exp->op != TOKstring && exp->op != TOKint64 && exp->op != TOKerror)
|
||||
{
|
||||
error("case must be a string or an integral constant, not %s", exp->toChars());
|
||||
exp = new IntegerExp(0);
|
||||
|
@ -3175,13 +3189,19 @@ Statement *CaseRangeStatement::semantic(Scope *sc)
|
|||
first = first->semantic(sc);
|
||||
first = first->implicitCastTo(sc, sw->condition->type);
|
||||
first = first->optimize(WANTvalue | WANTinterpret);
|
||||
uinteger_t fval = first->toInteger();
|
||||
|
||||
|
||||
last = last->semantic(sc);
|
||||
last = last->implicitCastTo(sc, sw->condition->type);
|
||||
last = last->optimize(WANTvalue | WANTinterpret);
|
||||
|
||||
if (first->op == TOKerror || last->op == TOKerror)
|
||||
return statement ? statement->semantic(sc) : NULL;
|
||||
|
||||
uinteger_t fval = first->toInteger();
|
||||
uinteger_t lval = last->toInteger();
|
||||
|
||||
|
||||
if ( (first->type->isunsigned() && fval > lval) ||
|
||||
(!first->type->isunsigned() && (sinteger_t)fval > (sinteger_t)lval))
|
||||
{
|
||||
|
@ -3210,7 +3230,7 @@ Statement *CaseRangeStatement::semantic(Scope *sc)
|
|||
{
|
||||
Statement *s = statement;
|
||||
if (i != lval) // if not last case
|
||||
s = new ExpStatement(loc, NULL);
|
||||
s = new ExpStatement(loc, (Expression *)NULL);
|
||||
Expression *e = new IntegerExp(loc, i, first->type);
|
||||
Statement *cs = new CaseStatement(loc, e, s);
|
||||
statements->push(cs);
|
||||
|
@ -3527,7 +3547,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
|||
Type *tfret = tf->nextOf();
|
||||
if (tfret)
|
||||
{
|
||||
if (!exp->type->equals(tfret))
|
||||
if (tfret != Type::terror && !exp->type->equals(tfret))
|
||||
error("mismatched function return type inference of %s and %s",
|
||||
exp->type->toChars(), tfret->toChars());
|
||||
|
||||
|
@ -4003,7 +4023,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
|||
VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie);
|
||||
|
||||
Statements *cs = new Statements();
|
||||
cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
|
||||
cs->push(new ExpStatement(loc, tmp));
|
||||
|
||||
#if IN_LLVM
|
||||
// LDC: Build args
|
||||
|
@ -4045,7 +4065,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
|||
tmp->storage_class |= STCgshared | STCstatic;
|
||||
|
||||
Statements *cs = new Statements();
|
||||
cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
|
||||
cs->push(new ExpStatement(loc, tmp));
|
||||
|
||||
#if IN_LLVM
|
||||
// LDC: Build args
|
||||
|
@ -4148,6 +4168,8 @@ Statement *WithStatement::semantic(Scope *sc)
|
|||
//printf("WithStatement::semantic()\n");
|
||||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
if (exp->op == TOKerror)
|
||||
return NULL;
|
||||
if (exp->op == TOKimport)
|
||||
{ ScopeExp *es = (ScopeExp *)exp;
|
||||
|
||||
|
@ -4537,7 +4559,7 @@ int OnScopeStatement::usesEH()
|
|||
return 1;
|
||||
}
|
||||
|
||||
void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
|
||||
Statement *OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
|
||||
{
|
||||
//printf("OnScopeStatement::scopeCode()\n");
|
||||
//print();
|
||||
|
@ -4557,17 +4579,17 @@ void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexc
|
|||
case TOKon_scope_success:
|
||||
{
|
||||
/* Create:
|
||||
* sentry: int x = 0;
|
||||
* sexception: x = 1;
|
||||
* sentry: bool x = false;
|
||||
* sexception: x = true;
|
||||
* sfinally: if (!x) statement;
|
||||
*/
|
||||
Identifier *id = Lexer::uniqueId("__os");
|
||||
|
||||
ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0));
|
||||
VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie);
|
||||
*sentry = new DeclarationStatement(loc, v);
|
||||
ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0, 0, Type::tbool));
|
||||
VarDeclaration *v = new VarDeclaration(loc, Type::tbool, id, ie);
|
||||
*sentry = new ExpStatement(loc, v);
|
||||
|
||||
Expression *e = new IntegerExp(1);
|
||||
Expression *e = new IntegerExp(0, 1, Type::tbool);
|
||||
e = new AssignExp(0, new VarExp(0, v), e);
|
||||
*sexception = new ExpStatement(0, e);
|
||||
|
||||
|
@ -4581,6 +4603,7 @@ void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexc
|
|||
default:
|
||||
assert(0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/******************************** ThrowStatement ***************************/
|
||||
|
@ -4611,6 +4634,8 @@ Statement *ThrowStatement::semantic(Scope *sc)
|
|||
#endif
|
||||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
if (exp->op == TOKerror)
|
||||
return this;
|
||||
ClassDeclaration *cd = exp->type->toBasetype()->isClassHandle();
|
||||
if (!cd || ((cd != ClassDeclaration::throwable) && !ClassDeclaration::throwable->isBaseOf(cd, NULL)))
|
||||
error("can only throw class objects derived from Throwable, not type %s", exp->type->toChars());
|
||||
|
@ -4697,6 +4722,57 @@ void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||
}
|
||||
|
||||
|
||||
/******************************** DebugStatement **************************/
|
||||
|
||||
DebugStatement::DebugStatement(Loc loc, Statement *statement)
|
||||
: Statement(loc)
|
||||
{
|
||||
this->statement = statement;
|
||||
}
|
||||
|
||||
Statement *DebugStatement::syntaxCopy()
|
||||
{
|
||||
DebugStatement *s = new DebugStatement(loc,
|
||||
statement ? statement->syntaxCopy() : NULL);
|
||||
return s;
|
||||
}
|
||||
|
||||
Statement *DebugStatement::semantic(Scope *sc)
|
||||
{
|
||||
if (statement)
|
||||
{
|
||||
sc = sc->push();
|
||||
sc->flags |= SCOPEdebug;
|
||||
statement = statement->semantic(sc);
|
||||
sc->pop();
|
||||
}
|
||||
return statement;
|
||||
}
|
||||
|
||||
Statements *DebugStatement::flatten(Scope *sc)
|
||||
{
|
||||
Statements *a = statement ? statement->flatten(sc) : NULL;
|
||||
if (a)
|
||||
{ for (size_t i = 0; i < a->dim; i++)
|
||||
{ Statement *s = (Statement *)a->data[i];
|
||||
|
||||
s = new DebugStatement(loc, s);
|
||||
a->data[i] = s;
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void DebugStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (statement)
|
||||
{
|
||||
statement->toCBuffer(buf, hgs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************** GotoStatement ***************************/
|
||||
|
||||
GotoStatement::GotoStatement(Loc loc, Identifier *ident)
|
||||
|
@ -4817,7 +4893,7 @@ Statements *LabelStatement::flatten(Scope *sc)
|
|||
{
|
||||
if (!a->dim)
|
||||
{
|
||||
a->push(new ExpStatement(loc, NULL));
|
||||
a->push(new ExpStatement(loc, (Expression *)NULL));
|
||||
}
|
||||
Statement *s = (Statement *)a->data[0];
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ struct Expression;
|
|||
struct LabelDsymbol;
|
||||
struct Identifier;
|
||||
struct IfStatement;
|
||||
struct DeclarationStatement;
|
||||
struct ExpStatement;
|
||||
struct DefaultStatement;
|
||||
struct VarDeclaration;
|
||||
struct Condition;
|
||||
|
@ -113,9 +113,6 @@ struct Statement : Object
|
|||
void error(const char *format, ...) IS_PRINTF(2);
|
||||
void warning(const char *format, ...) IS_PRINTF(2);
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual TryCatchStatement *isTryCatchStatement() { return NULL; }
|
||||
virtual GotoStatement *isGotoStatement() { return NULL; }
|
||||
virtual AsmStatement *isAsmStatement() { return NULL; }
|
||||
virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; }
|
||||
#if IN_LLVM
|
||||
virtual LabelStatement *isLabelStatement() { return NULL; }
|
||||
|
@ -133,7 +130,7 @@ struct Statement : Object
|
|||
virtual int blockExit(bool mustNotThrow);
|
||||
virtual int comeFrom();
|
||||
virtual int isEmpty();
|
||||
virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
virtual Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
virtual Statements *flatten(Scope *sc);
|
||||
virtual Expression *interpret(InterState *istate);
|
||||
|
||||
|
@ -145,7 +142,7 @@ struct Statement : Object
|
|||
virtual void toIR(IRState *irs);
|
||||
|
||||
// Avoid dynamic_cast
|
||||
virtual DeclarationStatement *isDeclarationStatement() { return NULL; }
|
||||
virtual ExpStatement *isExpStatement() { return NULL; }
|
||||
virtual CompoundStatement *isCompoundStatement() { return NULL; }
|
||||
virtual ReturnStatement *isReturnStatement() { return NULL; }
|
||||
virtual IfStatement *isIfStatement() { return NULL; }
|
||||
|
@ -170,12 +167,14 @@ struct ExpStatement : Statement
|
|||
Expression *exp;
|
||||
|
||||
ExpStatement(Loc loc, Expression *exp);
|
||||
ExpStatement(Loc loc, Dsymbol *s);
|
||||
Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit(bool mustNotThrow);
|
||||
int isEmpty();
|
||||
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
|
@ -183,6 +182,7 @@ struct ExpStatement : Statement
|
|||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
ExpStatement *isExpStatement() { return this; }
|
||||
#if IN_LLVM
|
||||
void toNakedIR(IRState *irs);
|
||||
#endif
|
||||
|
@ -199,20 +199,6 @@ struct CompileStatement : Statement
|
|||
Statement *semantic(Scope *sc);
|
||||
};
|
||||
|
||||
struct DeclarationStatement : ExpStatement
|
||||
{
|
||||
// Doing declarations as an expression, rather than a statement,
|
||||
// makes inlining functions much easier.
|
||||
|
||||
DeclarationStatement(Loc loc, Dsymbol *s);
|
||||
DeclarationStatement(Loc loc, Expression *exp);
|
||||
Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
|
||||
DeclarationStatement *isDeclarationStatement() { return this; }
|
||||
};
|
||||
|
||||
struct CompoundStatement : Statement
|
||||
{
|
||||
Statements *statements;
|
||||
|
@ -351,7 +337,7 @@ struct ForStatement : Statement
|
|||
ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
|
@ -764,7 +750,6 @@ struct TryCatchStatement : Statement
|
|||
|
||||
void toIR(IRState *irs);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
TryCatchStatement *isTryCatchStatement() { return this; }
|
||||
};
|
||||
|
||||
struct Catch : Object
|
||||
|
@ -813,7 +798,7 @@ struct OnScopeStatement : Statement
|
|||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
@ -851,6 +836,17 @@ struct VolatileStatement : Statement
|
|||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct DebugStatement : Statement
|
||||
{
|
||||
Statement *statement;
|
||||
|
||||
DebugStatement(Loc loc, Statement *statement);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Statements *flatten(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct GotoStatement : Statement
|
||||
{
|
||||
Identifier *ident;
|
||||
|
@ -866,7 +862,6 @@ struct GotoStatement : Statement
|
|||
|
||||
void toIR(IRState *irs);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
GotoStatement *isGotoStatement() { return this; }
|
||||
};
|
||||
|
||||
struct LabelStatement : Statement
|
||||
|
@ -928,7 +923,6 @@ struct AsmStatement : Statement
|
|||
Expression *interpret(InterState *istate);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual AsmStatement *isAsmStatement() { return this; }
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -52,10 +52,12 @@ void StaticAssert::semantic(Scope *sc)
|
|||
|
||||
void StaticAssert::semantic2(Scope *sc)
|
||||
{
|
||||
Expression *e;
|
||||
|
||||
//printf("StaticAssert::semantic2() %s\n", toChars());
|
||||
e = exp->semantic(sc);
|
||||
ScopeDsymbol *sd = new ScopeDsymbol();
|
||||
sc = sc->push(sd);
|
||||
sc->flags |= SCOPEstaticassert;
|
||||
Expression *e = exp->semantic(sc);
|
||||
sc = sc->pop();
|
||||
if (e->op == TOKerror)
|
||||
return;
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
|
|
|
@ -254,6 +254,57 @@ int AggregateDeclaration::isNested()
|
|||
return isnested;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* If field[indx] is not part of a union, return indx.
|
||||
* Otherwise, return the lowest field index of the union.
|
||||
*/
|
||||
int AggregateDeclaration::firstFieldInUnion(int indx)
|
||||
{
|
||||
if (isUnionDeclaration())
|
||||
return 0;
|
||||
VarDeclaration * vd = (VarDeclaration *)fields.data[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];
|
||||
if (v->offset != vd->offset)
|
||||
return firstNonZero;
|
||||
--indx;
|
||||
/* If it is a zero-length field, it's ambiguous: we don't know if it is
|
||||
* in the union unless we find an earlier non-zero sized field with the
|
||||
* same offset.
|
||||
*/
|
||||
if (v->size(loc) != 0)
|
||||
firstNonZero = indx;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Count the number of fields starting at firstIndex which are part of the
|
||||
* same union as field[firstIndex]. If not a union, return 1.
|
||||
*/
|
||||
int AggregateDeclaration::numFieldsInUnion(int firstIndex)
|
||||
{
|
||||
VarDeclaration * vd = (VarDeclaration *)fields.data[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.
|
||||
*/
|
||||
if (vd->size(loc) == 0 && !isUnionDeclaration() &&
|
||||
firstFieldInUnion(firstIndex) == firstIndex)
|
||||
return 1;
|
||||
int count = 1;
|
||||
for (int i = firstIndex+1; i < fields.dim; ++i)
|
||||
{
|
||||
VarDeclaration * v = (VarDeclaration *)fields.data[i];
|
||||
// If offsets are different, they are not in the same union
|
||||
if (v->offset != vd->offset)
|
||||
break;
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/********************************* StructDeclaration ****************************/
|
||||
|
||||
|
@ -630,7 +681,7 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
|
|||
{
|
||||
//printf("%s.StructDeclaration::search('%s')\n", toChars(), ident->toChars());
|
||||
|
||||
if (scope)
|
||||
if (scope && !symtab)
|
||||
semantic(scope);
|
||||
|
||||
if (!members || !symtab)
|
||||
|
|
|
@ -4215,7 +4215,7 @@ void TemplateInstance::semanticTiargs(Scope *sc)
|
|||
void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags)
|
||||
{
|
||||
// Run semantic on each argument, place results in tiargs[]
|
||||
//printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
|
||||
//printf("+TemplateInstance::semanticTiargs()\n");
|
||||
if (!tiargs)
|
||||
return;
|
||||
for (size_t j = 0; j < tiargs->dim; j++)
|
||||
|
@ -4239,7 +4239,9 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
|
|||
* match with an 'alias' parameter. Instead, do the
|
||||
* const substitution in TemplateValueParameter::matchArg().
|
||||
*/
|
||||
if (ea->op != TOKvar || flags & 1)
|
||||
if (flags & 1) // only used by __traits, must not interpret the args
|
||||
ea = ea->optimize(WANTvalue);
|
||||
else if (ea->op != TOKvar)
|
||||
ea = ea->optimize(WANTvalue | WANTinterpret);
|
||||
tiargs->data[j] = ea;
|
||||
}
|
||||
|
@ -4288,7 +4290,9 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
|
|||
}
|
||||
assert(ea);
|
||||
ea = ea->semantic(sc);
|
||||
if (ea->op != TOKvar || flags & 1)
|
||||
if (flags & 1) // only used by __traits, must not interpret the args
|
||||
ea = ea->optimize(WANTvalue);
|
||||
else if (ea->op != TOKvar)
|
||||
ea = ea->optimize(WANTvalue | WANTinterpret);
|
||||
tiargs->data[j] = ea;
|
||||
if (ea->op == TOKtype)
|
||||
|
@ -4321,7 +4325,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
|
|||
//printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]);
|
||||
}
|
||||
#if 0
|
||||
printf("-TemplateInstance::semanticTiargs('%s', this=%p)\n", toChars(), this);
|
||||
printf("-TemplateInstance::semanticTiargs()\n");
|
||||
for (size_t j = 0; j < tiargs->dim; j++)
|
||||
{
|
||||
Object *o = (Object *)tiargs->data[j];
|
||||
|
@ -4718,8 +4722,8 @@ Identifier *TemplateInstance::genIdent(Objects *args)
|
|||
Lea:
|
||||
sinteger_t v;
|
||||
real_t r;
|
||||
|
||||
ea = ea->optimize(WANTvalue | WANTinterpret);
|
||||
// Don't interpret it yet, it might actually be an alias
|
||||
ea = ea->optimize(WANTvalue);
|
||||
if (ea->op == TOKvar)
|
||||
{
|
||||
sa = ((VarExp *)ea)->var;
|
||||
|
@ -4737,6 +4741,8 @@ Identifier *TemplateInstance::genIdent(Objects *args)
|
|||
{ ea->error("tuple is not a valid template value argument");
|
||||
continue;
|
||||
}
|
||||
// Now that we know it is not an alias, we MUST obtain a value
|
||||
ea = ea->optimize(WANTvalue | WANTinterpret);
|
||||
#if 1
|
||||
/* Use deco that matches what it would be for a function parameter
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
@ -196,6 +196,21 @@ Expression *TraitsExp::semantic(Scope *sc)
|
|||
StringExp *se = new StringExp(loc, s->ident->toChars());
|
||||
return se->semantic(sc);
|
||||
}
|
||||
else if (ident == Id::parent)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (Object *)args->data[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
if (s)
|
||||
s = s->toParent();
|
||||
if (!s)
|
||||
{
|
||||
error("argument %s has no parent", o->toChars());
|
||||
goto Lfalse;
|
||||
}
|
||||
return (new DsymbolExp(loc, s))->semantic(sc);
|
||||
}
|
||||
|
||||
#endif
|
||||
else if (ident == Id::hasMember ||
|
||||
|
|
|
@ -991,8 +991,8 @@ namespace AsmParserx8632
|
|||
{ "pop", Op_DstW },
|
||||
{ "popa", Op_SizedStack }, // For intel this is always 16-bit
|
||||
{ "popad", Op_SizedStack }, // GAS doesn't accept 'popad' -- these clobber everything, but supposedly it would be used to preserve clobbered regs
|
||||
{ "popf", Op_SizedStack }, // rewrite the insn with a special case
|
||||
{ "popfd", Op_SizedStack },
|
||||
{ "popf", Op_0 }, // rewrite the insn with a special case
|
||||
{ "popfd", Op_0 },
|
||||
{ "por", Op_DstSrcMMX },
|
||||
{ "prefetchnta", Op_SrcMemNT },
|
||||
{ "prefetcht0", Op_SrcMemNT },
|
||||
|
@ -1033,8 +1033,8 @@ namespace AsmParserx8632
|
|||
{ "push", Op_push },
|
||||
{ "pusha", Op_SizedStack },
|
||||
{ "pushad", Op_SizedStack },
|
||||
{ "pushf", Op_SizedStack },
|
||||
{ "pushfd", Op_SizedStack },
|
||||
{ "pushf", Op_0 },
|
||||
{ "pushfd", Op_0 },
|
||||
{ "pxor", Op_DstSrcMMX },
|
||||
{ "rcl", Op_Shift }, // limited src operands -- change to shift
|
||||
{ "rcpps", Op_DstSrcSSE },
|
||||
|
|
|
@ -1111,8 +1111,8 @@ namespace AsmParserx8664
|
|||
{ "pmullw", Op_DstSrcMMX },
|
||||
{ "pmuludq", Op_DstSrcMMX }, // also sse
|
||||
{ "pop", Op_DstW },
|
||||
{ "popf", Op_SizedStack }, // rewrite the insn with a special case
|
||||
{ "popfq", Op_SizedStack },
|
||||
{ "popf", Op_0 }, // rewrite the insn with a special case
|
||||
{ "popfq", Op_0 },
|
||||
{ "popq", Op_push },
|
||||
{ "por", Op_DstSrcMMX },
|
||||
{ "prefetchnta", Op_SrcMemNT },
|
||||
|
@ -1156,8 +1156,8 @@ namespace AsmParserx8664
|
|||
{ "punpcklqdq",Op_DstSrcMMX },
|
||||
{ "punpcklwd", Op_DstSrcMMX },
|
||||
{ "push", Op_push },
|
||||
{ "pushf", Op_SizedStack },
|
||||
{ "pushfq", Op_SizedStack },
|
||||
{ "pushf", Op_0 },
|
||||
{ "pushfq", Op_0 },
|
||||
{ "pushq", Op_push },
|
||||
{ "pxor", Op_DstSrcMMX },
|
||||
{ "rcl", Op_Shift }, // limited src operands -- change to shift
|
||||
|
|
|
@ -415,7 +415,7 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op)
|
|||
DtoArrayInit(loc, lhs, rhs, op);
|
||||
}
|
||||
#if DMDV2
|
||||
else if (DtoArrayElementType(t)->equals(t2)) {
|
||||
else if (stripModifiers(DtoArrayElementType(t))->equals(stripModifiers(t2))) {
|
||||
DtoArrayInit(loc, s, rhs, op);
|
||||
}
|
||||
else if (op != -1 && op != TOKblit && arrayNeedsPostblit(t)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue