Merged dmdfe 2.031.

This commit is contained in:
Robert Clipsham
2009-07-07 02:26:11 +01:00
parent e5b7c25597
commit b73e45940a
40 changed files with 1432 additions and 377 deletions

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -435,6 +435,12 @@ Expression *AssignExp::buildArrayLoop(Arguments *fparams)
/* Evaluate assign expressions right to left
*/
Expression *ex2 = e2->buildArrayLoop(fparams);
/* Need the cast because:
* b = c + p[i];
* where b is a byte fails because (c + p[i]) is an int
* which cannot be implicitly cast to byte.
*/
ex2 = new CastExp(0, ex2, e1->type->nextOf());
Expression *ex1 = e1->buildArrayLoop(fparams);
Argument *param = (Argument *)fparams->data[0];
param->storageClass = 0;

View File

@@ -26,6 +26,9 @@
#include "module.h"
#include "parse.h"
#include "template.h"
#if TARGET_NET
#include "frontend.net/pragma.h"
#endif
#if IN_LLVM
#include "../gen/enums.h"
@@ -74,6 +77,41 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
return m;
}
void AttribDeclaration::semanticNewSc(Scope *sc,
unsigned stc, enum LINK linkage, enum PROT protection, int explicitProtection,
unsigned structalign)
{
if (decl)
{
Scope *newsc = sc;
if (stc != sc->stc ||
linkage != sc->linkage ||
protection != sc->protection ||
explicitProtection != sc->explicitProtection ||
structalign != sc->structalign)
{
// create new one for changes
newsc = new Scope(*sc);
newsc->flags &= ~SCOPEfree;
newsc->stc = stc;
newsc->linkage = linkage;
newsc->protection = protection;
newsc->explicitProtection = explicitProtection;
newsc->structalign = structalign;
}
for (unsigned i = 0; i < decl->dim; i++)
{ Dsymbol *s = (Dsymbol *)decl->data[i];
s->semantic(newsc);
}
if (newsc != sc)
{
sc->offset = newsc->offset;
newsc->pop();
}
}
}
void AttribDeclaration::semantic(Scope *sc)
{
Array *d = include(sc, NULL);
@@ -305,10 +343,38 @@ Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
void StorageClassDeclaration::semantic(Scope *sc)
{
if (decl)
{ unsigned stc_save = sc->stc;
{
#if 1
unsigned scstc = sc->stc;
if (stc & (STCauto | STCscope | STCstatic | STCextern))
sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern);
/* These sets of storage classes are mutually exclusive,
* so choose the innermost or most recent one.
*/
if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared))
scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared);
if (stc & (STCconst | STCimmutable | STCmanifest))
scstc &= ~(STCconst | STCimmutable | STCmanifest);
if (stc & (STCgshared | STCshared | STCtls))
scstc &= ~(STCgshared | STCshared | STCtls);
scstc |= stc;
semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
#else
unsigned stc_save = sc->stc;
/* These sets of storage classes are mutually exclusive,
* so choose the innermost or most recent one.
*/
if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared))
sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared);
if (stc & (STCconst | STCimmutable | STCmanifest))
sc->stc &= ~(STCconst | STCimmutable | STCmanifest);
if (stc & (STCgshared | STCshared | STCtls))
sc->stc &= ~(STCgshared | STCshared | STCtls);
sc->stc |= stc;
for (unsigned i = 0; i < decl->dim; i++)
{
@@ -317,9 +383,8 @@ void StorageClassDeclaration::semantic(Scope *sc)
s->semantic(sc);
}
sc->stc = stc_save;
#endif
}
else
sc->stc = stc;
}
void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, int stc)
@@ -393,7 +458,11 @@ void LinkDeclaration::semantic(Scope *sc)
{
//printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
if (decl)
{ enum LINK linkage_save = sc->linkage;
{
#if 1
semanticNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign);
#else
enum LINK linkage_save = sc->linkage;
sc->linkage = linkage;
for (unsigned i = 0; i < decl->dim; i++)
@@ -403,10 +472,7 @@ void LinkDeclaration::semantic(Scope *sc)
s->semantic(sc);
}
sc->linkage = linkage_save;
}
else
{
sc->linkage = linkage;
#endif
}
}
@@ -481,7 +547,11 @@ Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
void ProtDeclaration::semantic(Scope *sc)
{
if (decl)
{ enum PROT protection_save = sc->protection;
{
#if 1
semanticNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign);
#else
enum PROT protection_save = sc->protection;
int explicitProtection_save = sc->explicitProtection;
sc->protection = protection;
@@ -494,15 +564,13 @@ void ProtDeclaration::semantic(Scope *sc)
}
sc->protection = protection_save;
sc->explicitProtection = explicitProtection_save;
}
else
{ sc->protection = protection;
sc->explicitProtection = 1;
#endif
}
}
void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{ const char *p;
void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, enum PROT protection)
{
const char *p;
switch (protection)
{
@@ -516,6 +584,12 @@ void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
break;
}
buf->writestring(p);
buf->writeByte(' ');
}
void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
protectionToCBuffer(buf, protection);
AttribDeclaration::toCBuffer(buf, hgs);
}
@@ -545,7 +619,12 @@ void AlignDeclaration::semantic(Scope *sc)
//printf("\tAlignDeclaration::semantic '%s'\n",toChars());
if (decl)
{ unsigned salign_save = sc->structalign;
{
#if 1
semanticNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign);
#else
unsigned salign_save = sc->structalign;
#if IN_DMD
sc->structalign = salign;
#endif
@@ -553,6 +632,7 @@ void AlignDeclaration::semantic(Scope *sc)
{
Dsymbol *s = (Dsymbol *)decl->data[i];
#if IN_LLVM
if (s->isStructDeclaration() && salign == 1)
{
sc->structalign = salign;
@@ -561,10 +641,14 @@ void AlignDeclaration::semantic(Scope *sc)
}
else
{
#endif
s->semantic(sc);
#if IN_LLVM
}
#endif
}
sc->structalign = salign_save;
#endif
}
else
assert(0 && "what kind of align use triggers this?");
@@ -584,7 +668,6 @@ AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl)
{
this->loc = loc;
this->isunion = isunion;
this->scope = NULL;
this->sem = 0;
}
@@ -895,7 +978,27 @@ void PragmaDeclaration::semantic(Scope *sc)
}
goto Lnodecl;
}
#if TARGET_NET
else if (ident == Lexer::idPool("assembly"))
{
if (!args || args->dim != 1)
error("pragma has invalid number of arguments");
else
{
Expression *e = (Expression *)args->data[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
args->data[0] = (void *)e;
if (e->op != TOKstring)
{
error("string expected, not '%s'", e->toChars());
}
PragmaScope* pragma = new PragmaScope(this, sc->parent, static_cast<StringExp*>(e));
decl = new Array;
decl->push(pragma);
}
}
#endif // TARGET_NET
// LDC
#if IN_LLVM

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -36,6 +36,9 @@ struct AttribDeclaration : Dsymbol
AttribDeclaration(Array *decl);
virtual Array *include(Scope *sc, ScopeDsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void semanticNewSc(Scope *sc,
unsigned newstc, enum LINK linkage, enum PROT protection, int explictProtection,
unsigned structalign);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
@@ -92,6 +95,8 @@ struct ProtDeclaration : AttribDeclaration
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static void protectionToCBuffer(OutBuffer *buf, enum PROT protection);
};
struct AlignDeclaration : AttribDeclaration
@@ -107,7 +112,6 @@ struct AlignDeclaration : AttribDeclaration
struct AnonDeclaration : AttribDeclaration
{
int isunion;
Scope *scope; // !=NULL means context to use
int sem; // 1 if successful semantic()
AnonDeclaration(Loc loc, int isunion, Array *decl);

View File

@@ -33,6 +33,7 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
if (match)
{ TY tyfrom = type->toBasetype()->ty;
TY tyto = t->toBasetype()->ty;
#if DMDV1
if (global.params.warnings &&
Type::impcnvWarn[tyfrom][tyto] &&
op != TOKint64)
@@ -41,7 +42,6 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
if (e->op == TOKint64)
return e->implicitCastTo(sc, t);
if (tyfrom == Tint32 &&
(op == TOKadd || op == TOKmin ||
op == TOKand || op == TOKor || op == TOKxor)
@@ -61,6 +61,7 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
toChars(), type->toChars(), t->toChars());
}
}
#endif
#if DMDV2
if (match == MATCHconst && t == type->constOf())
{
@@ -144,6 +145,16 @@ MATCH Expression::implicitConvTo(Type *t)
MATCH match = type->implicitConvTo(t);
if (match != MATCHnomatch)
return match;
/* See if we can do integral narrowing conversions
*/
if (type->isintegral() && t->isintegral() &&
type->isTypeBasic() && t->isTypeBasic())
{ IntRange ir = getIntRange();
if (ir.imax <= t->sizemask())
return MATCHconvert;
}
#if 0
Type *tb = t->toBasetype();
if (tb->ty == Tdelegate)
@@ -676,18 +687,72 @@ MATCH DelegateExp::implicitConvTo(Type *t)
return result;
}
MATCH OrExp::implicitConvTo(Type *t)
{
MATCH result = Expression::implicitConvTo(t);
if (result == MATCHnomatch)
{
MATCH m1 = e1->implicitConvTo(t);
MATCH m2 = e2->implicitConvTo(t);
// Pick the worst match
result = (m1 < m2) ? m1 : m2;
}
return result;
}
MATCH XorExp::implicitConvTo(Type *t)
{
MATCH result = Expression::implicitConvTo(t);
if (result == MATCHnomatch)
{
MATCH m1 = e1->implicitConvTo(t);
MATCH m2 = e2->implicitConvTo(t);
// Pick the worst match
result = (m1 < m2) ? m1 : m2;
}
return result;
}
MATCH CondExp::implicitConvTo(Type *t)
{
MATCH m1;
MATCH m2;
m1 = e1->implicitConvTo(t);
m2 = e2->implicitConvTo(t);
MATCH m1 = e1->implicitConvTo(t);
MATCH m2 = e2->implicitConvTo(t);
//printf("CondExp: m1 %d m2 %d\n", m1, m2);
// Pick the worst match
return (m1 < m2) ? m1 : m2;
}
MATCH CommaExp::implicitConvTo(Type *t)
{
return e2->implicitConvTo(t);
}
MATCH CastExp::implicitConvTo(Type *t)
{
#if 0
printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
toChars(), type->toChars(), t->toChars());
#endif
MATCH result;
result = type->implicitConvTo(t);
if (result == MATCHnomatch)
{
if (t->isintegral() &&
e1->type->isintegral() &&
e1->implicitConvTo(t) != MATCHnomatch)
result = MATCHconvert;
else
result = Expression::implicitConvTo(t);
}
return result;
}
/* ==================== castTo ====================== */
@@ -1258,22 +1323,35 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t)
f = f->overloadExactMatch(tb->nextOf(), m);
if (f)
{
if (tb->ty == Tdelegate && f->needThis() && hasThis(sc))
if (tb->ty == Tdelegate)
{
e = new DelegateExp(loc, new ThisExp(loc), f);
e = e->semantic(sc);
}
else if (tb->ty == Tdelegate && f->isNested())
{
e = new DelegateExp(loc, new IntegerExp(0), f);
e = e->semantic(sc);
if (f->needThis() && hasThis(sc))
{
e = new DelegateExp(loc, new ThisExp(loc), f);
e = e->semantic(sc);
}
else if (f->isNested())
{
e = new DelegateExp(loc, new IntegerExp(0), f);
e = e->semantic(sc);
}
else if (f->needThis())
{ error("no 'this' to create delegate for %s", f->toChars());
e = new ErrorExp();
}
else
{ error("cannot cast from function pointer to delegate");
e = new ErrorExp();
}
}
else
{
e = new SymOffExp(loc, f, 0);
e->type = t;
}
#if DMDV2
f->tookAddressOf++;
#endif
return e;
}
}
@@ -1353,6 +1431,23 @@ Expression *CondExp::castTo(Scope *sc, Type *t)
return e;
}
Expression *CommaExp::castTo(Scope *sc, Type *t)
{
Expression *e2c = e2->castTo(sc, t);
Expression *e;
if (e2c != e2)
{
e = new CommaExp(loc, e1, e2c);
e->type = e2c->type;
}
else
{ e = this;
e->type = e2->type;
}
return e;
}
/* ==================== ====================== */
/****************************************
@@ -1777,3 +1872,226 @@ int arrayTypeCompatible(Loc loc, Type *t1, Type *t2)
}
return 0;
}
/******************************************************************/
/* Determine the integral ranges of an expression.
* This is used to determine if implicit narrowing conversions will
* be allowed.
*/
uinteger_t getMask(uinteger_t v)
{
uinteger_t u = 0;
if (v >= 0x80)
u = 0xFF;
while (u < v)
u = (u << 1) | 1;
return u;
}
IntRange Expression::getIntRange()
{
IntRange ir;
ir.imin = 0;
ir.imax = type->sizemask();
return ir;
}
IntRange IntegerExp::getIntRange()
{
IntRange ir;
ir.imin = value & type->sizemask();
ir.imax = ir.imin;
return ir;
}
IntRange CastExp::getIntRange()
{
IntRange ir;
ir = e1->getIntRange();
// Do sign extension
switch (e1->type->toBasetype()->ty)
{
case Tint8:
if (ir.imax & 0x80)
ir.imax |= 0xFFFFFFFFFFFFFF00ULL;
break;
case Tint16:
if (ir.imax & 0x8000)
ir.imax |= 0xFFFFFFFFFFFF0000ULL;
break;
case Tint32:
if (ir.imax & 0x80000000)
ir.imax |= 0xFFFFFFFF00000000ULL;
break;
}
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
//printf("CastExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
return ir;
}
IntRange DivExp::getIntRange()
{
if (!e1->type->isunsigned() && !e2->type->isunsigned())
return Expression::getIntRange();
IntRange ir;
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
ir.imin = ir1.imin / ir2.imax;
ir.imax = ir1.imax / ir2.imin;
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
//printf("DivExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
}
IntRange AndExp::getIntRange()
{
IntRange ir;
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
ir.imin = ir1.imin;
if (ir2.imin < ir.imin)
ir.imin = ir2.imin;
ir.imax = ir1.imax;
if (ir2.imax > ir.imax)
ir.imax = ir2.imax;
uinteger_t u;
u = getMask(ir1.imax);
ir.imin &= u;
ir.imax &= u;
u = getMask(ir2.imax);
ir.imin &= u;
ir.imax &= u;
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
//printf("AndExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
}
IntRange OrExp::getIntRange()
{
IntRange ir;
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
ir.imin = ir1.imin;
if (ir2.imin < ir.imin)
ir.imin = ir2.imin;
ir.imax = ir1.imax;
if (ir2.imax > ir.imax)
ir.imax = ir2.imax;
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
//printf("OrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
}
IntRange XorExp::getIntRange()
{
IntRange ir;
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
ir.imin = ir1.imin;
if (ir2.imin < ir.imin)
ir.imin = ir2.imin;
ir.imax = ir1.imax;
if (ir2.imax > ir.imax)
ir.imax = ir2.imax;
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
//printf("XorExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
}
IntRange ShlExp::getIntRange()
{
IntRange ir;
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
ir.imin = getMask(ir1.imin) << ir2.imin;
ir.imax = getMask(ir1.imax) << ir2.imax;
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
//printf("ShlExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
}
IntRange ShrExp::getIntRange()
{
if (!e1->type->isunsigned())
return Expression::getIntRange();
IntRange ir;
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
ir.imin = ir1.imin >> ir2.imax;
ir.imax = ir1.imax >> ir2.imin;
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
//printf("ShrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
}
IntRange UshrExp::getIntRange()
{
IntRange ir;
IntRange ir1 = e1->getIntRange();
IntRange ir2 = e2->getIntRange();
ir.imin = ir1.imin >> ir2.imax;
ir.imax = ir1.imax >> ir2.imin;
ir.imin &= type->sizemask();
ir.imax &= type->sizemask();
//printf("UshrExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax);
//e1->dump(0);
return ir;
}
IntRange CommaExp::getIntRange()
{
return e2->getIntRange();
}

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -233,14 +233,14 @@ void ClassDeclaration::semantic(Scope *sc)
ident = Identifier::generateId(id);
}
if (!scope)
{
if (!parent && sc->parent && !sc->parent->isModule())
parent = sc->parent;
if (!sc)
sc = scope;
if (!parent && sc->parent && !sc->parent->isModule())
parent = sc->parent;
type = type->semantic(loc, sc);
handle = type;
type = type->semantic(loc, sc);
handle = handle->semantic(loc, sc);
}
if (!members) // if forward reference
{ //printf("\tclass '%s' is forward referenced\n", toChars());
return;
@@ -275,7 +275,9 @@ void ClassDeclaration::semantic(Scope *sc)
// Expand any tuples in baseclasses[]
for (i = 0; i < baseclasses.dim; )
{ BaseClass *b = (BaseClass *)baseclasses.data[i];
//printf("test1 %s %s\n", toChars(), b->type->toChars());
b->type = b->type->semantic(loc, sc);
//printf("test2\n");
Type *tb = b->type->toBasetype();
if (tb->ty == Ttuple)
@@ -334,8 +336,14 @@ void ClassDeclaration::semantic(Scope *sc)
goto L7;
}
}
if (!tc->sym->symtab || tc->sym->sizeok == 0)
{ // Try to resolve forward reference
if (sc->mustsemantic && tc->sym->scope)
tc->sym->semantic(NULL);
}
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
{
//printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
//error("forward reference of base class %s", baseClass->toChars());
// Forward reference of base class, try again later
//printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
@@ -793,10 +801,15 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
//printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
if (scope)
semantic(scope);
{ Scope *sc = scope;
sc->mustsemantic++;
semantic(sc);
sc->mustsemantic--;
}
if (!members || !symtab || scope)
{ error("is forward referenced when looking for '%s'", ident->toChars());
{
error("is forward referenced when looking for '%s'", ident->toChars());
//*(char*)0=0;
return NULL;
}
@@ -1037,10 +1050,15 @@ void InterfaceDeclaration::semantic(Scope *sc)
//printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
if (inuse)
return;
if (!scope)
{ type = type->semantic(loc, sc);
handle = handle->semantic(loc, sc);
}
if (!sc)
sc = scope;
if (!parent && sc->parent && !sc->parent->isModule())
parent = sc->parent;
type = type->semantic(loc, sc);
handle = type;
if (!members) // if forward reference
{ //printf("\tinterface '%s' is forward referenced\n", toChars());
return;

View File

@@ -143,10 +143,11 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident)
"all",
"none",
// LDC
#if IN_LLVM
"LLVM", "LDC", "LLVM64",
"PPC", "PPC64",
"darwin","solaris","freebsd"
#endif
};
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)

View File

@@ -853,9 +853,13 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
Loc loc = e1->loc;
int cmp;
if (e1->op == TOKnull && e2->op == TOKnull)
if (e1->op == TOKnull)
{
cmp = 1;
cmp = (e2->op == TOKnull);
}
else if (e2->op == TOKnull)
{
cmp = 0;
}
else if (e1->op == TOKsymoff && e2->op == TOKsymoff)
{

View File

@@ -463,6 +463,7 @@ void AliasDeclaration::semantic(Scope *sc)
if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()))
goto L2; // it's a symbolic alias
#if DMDV2
if (storage_class & STCref)
{ // For 'ref' to be attached to function types, and picked
// up by Type::resolve(), it has to go into sc.
@@ -472,6 +473,7 @@ void AliasDeclaration::semantic(Scope *sc)
sc = sc->pop();
}
else
#endif
type->resolve(loc, sc, &e, &t, &s);
if (s)
{
@@ -488,7 +490,9 @@ void AliasDeclaration::semantic(Scope *sc)
t = e->type;
}
else if (t)
{
type = t;
}
if (overnext)
ScopeDsymbol::multiplyDefined(0, this, overnext);
this->inSemantic = 0;
@@ -511,7 +515,9 @@ void AliasDeclaration::semantic(Scope *sc)
if (overnext)
{
FuncAliasDeclaration *fa = new FuncAliasDeclaration(f);
#if IN_LLVM
fa->importprot = importprot;
#endif
if (!fa->overloadInsert(overnext))
ScopeDsymbol::multiplyDefined(0, f, overnext);
overnext = NULL;
@@ -527,6 +533,7 @@ void AliasDeclaration::semantic(Scope *sc)
s = NULL;
}
}
//printf("setting aliassym %p to %p\n", this, s);
aliassym = s;
this->inSemantic = 0;
}
@@ -624,12 +631,14 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
this->loc = loc;
offset = 0;
noauto = 0;
#if DMDV1
nestedref = 0;
#endif
ctorinit = 0;
aliassym = NULL;
onstack = 0;
canassign = 0;
value = NULL;
scope = NULL;
#if IN_LLVM
aggrIndex = 0;
@@ -730,10 +739,12 @@ void VarDeclaration::semantic(Scope *sc)
//printf("sc->stc = %x\n", sc->stc);
//printf("storage_class = x%x\n", storage_class);
#if DMDV2
if (storage_class & STCgshared && global.params.safe && !sc->module->safe)
{
error("__gshared not allowed in safe mode; use shared");
}
#endif
Dsymbol *parent = toParent();
FuncDeclaration *fd = parent->isFuncDeclaration();
@@ -851,7 +862,9 @@ Lagain:
if (!aad)
aad = parent->isAggregateDeclaration();
if (aad)
{ assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared)));
{
#if DMDV2
assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared)));
if (storage_class & (STCconst | STCimmutable) && init)
{
@@ -859,6 +872,7 @@ Lagain:
storage_class |= STCstatic;
}
else
#endif
aad->addField(sc, this);
}
@@ -891,11 +905,13 @@ Lagain:
}
}
#if DMDV2
if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref &&
ident != Id::This)
{
error("only parameters or foreach declarations can be ref");
}
#endif
if (type->isauto() && !noauto)
{
@@ -940,7 +956,9 @@ Lagain:
Expression *e1;
e1 = new VarExp(loc, this);
e = new AssignExp(loc, e1, e);
#if DMDV2
e->op = TOKconstruct;
#endif
e->type = e1->type; // don't type check this, it would fail
init = new ExpInitializer(loc, e);
return;
@@ -961,8 +979,10 @@ Lagain:
{
init = getExpInitializer();
}
#if DMDV2
// Default initializer is always a blit
op = TOKblit;
#endif
}
if (init)
@@ -1040,7 +1060,7 @@ Lagain:
else if (t->ty == Tstruct)
{
ei->exp = ei->exp->semantic(sc);
#if DMDV2
/* Look to see if initializer is a call to the constructor
*/
StructDeclaration *sd = ((TypeStruct *)t)->sym;
@@ -1078,7 +1098,7 @@ Lagain:
}
}
}
#endif
if (!ei->exp->implicitConvTo(type))
{ Type *ti = ei->exp->type->toBasetype();
// Don't cast away invariant or mutability in initializer
@@ -1132,11 +1152,12 @@ Lagain:
{
if (global.gag == 0)
global.errors = errors; // act as if nothing happened
#if DMDV2
/* Save scope for later use, to try again
*/
scope = new Scope(*sc);
scope->setNoFree();
#endif
}
else if (ei)
{
@@ -1150,6 +1171,7 @@ Lagain:
{
ei->exp = e; // no errors, keep result
}
#if DMDV2
else
{
/* Save scope for later use, to try again
@@ -1157,6 +1179,7 @@ Lagain:
scope = new Scope(*sc);
scope->setNoFree();
}
#endif
}
else
init = i2; // no errors, keep result
@@ -1220,10 +1243,12 @@ void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring(ident->toChars());
if (init)
{ buf->writestring(" = ");
#if DMDV2
ExpInitializer *ie = init->isExpInitializer();
if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs);
else
#endif
init->toCBuffer(buf, hgs);
}
buf->writeByte(';');
@@ -1588,9 +1613,10 @@ Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s)
void TypeInfoDeclaration::semantic(Scope *sc)
{
assert(linkage == LINKc);
// LDC
#if IN_LLVM
if (!global.params.useAvailableExternally)
availableExternally = false;
#endif
}
/***************************** TypeInfoConstDeclaration **********************/

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -269,7 +269,6 @@ struct VarDeclaration : Declaration
Dsymbol *aliassym; // if redone as alias to another symbol
Expression *value; // when interpreting, this is the value
// (NULL if value not determinable)
Scope *scope; // !=NULL means context to use
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
Dsymbol *syntaxCopy(Dsymbol *);
@@ -668,7 +667,6 @@ struct FuncDeclaration : Declaration
// of the 'introducing' function
// this one is overriding
int inferRetType; // !=0 if return type is to be inferred
Scope *scope; // !=NULL means context to use
// Things that should really go into Scope
int hasReturnExp; // 1 if there's a return exp; statement

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -48,6 +48,7 @@ Dsymbol::Dsymbol()
#endif
this->loc = 0;
this->comment = NULL;
this->scope = NULL;
#if IN_LLVM
this->llvmInternal = LLVMnone;
@@ -67,6 +68,7 @@ Dsymbol::Dsymbol(Identifier *ident)
#endif
this->loc = 0;
this->comment = NULL;
this->scope = NULL;
#if IN_LLVM
this->llvmInternal = LLVMnone;
@@ -193,6 +195,16 @@ char *Dsymbol::toPrettyChars()
if (q == s)
break;
q--;
#if TARGET_NET
if (AggregateDeclaration* ad = p->isAggregateDeclaration())
{
if (ad->isNested() && p->parent && p->parent->isAggregateDeclaration())
{
*q = '/';
continue;
}
}
#endif
*q = '.';
}
return s;
@@ -269,24 +281,53 @@ int Dsymbol::isAnonymous()
return ident ? 0 : 1;
}
/*************************************
* Set scope for future semantic analysis so we can
* deal better with forward references.
*/
void Dsymbol::setScope(Scope *sc)
{
//printf("Dsymbol::setScope() %p %s\n", this, toChars());
if (!sc->nofree)
sc->setNoFree(); // may need it even after semantic() finishes
scope = sc;
}
/*************************************
* Does semantic analysis on the public face of declarations.
*/
void Dsymbol::semantic(Scope *sc)
{
error("%p has no semantic routine", this);
}
/*************************************
* Does semantic analysis on initializers and members of aggregates.
*/
void Dsymbol::semantic2(Scope *sc)
{
// Most Dsymbols have no further semantic analysis needed
}
/*************************************
* Does semantic analysis on function bodies.
*/
void Dsymbol::semantic3(Scope *sc)
{
// Most Dsymbols have no further semantic analysis needed
}
/*************************************
* Look for function inlining possibilities.
*/
void Dsymbol::inlineScan()
{
// Most Dsymbols have no further semantic analysis needed
// Most Dsymbols aren't functions
}
/*********************************************
@@ -344,7 +385,7 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
return NULL;
}
ti->tempdecl = td;
if (!ti->semanticdone)
if (!ti->semanticRun)
ti->semantic(sc);
sm = ti->toAlias();
break;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -74,15 +74,14 @@ struct Expression;
struct DeleteDeclaration;
struct HdrGenState;
struct OverloadSet;
#if TARGET_NET
struct PragmaScope;
#endif
#if IN_LLVM
struct TypeInfoDeclaration;
struct ClassInfoDeclaration;
#endif
#if IN_DMD
struct Symbol;
#endif
#if IN_GCC
union tree_node;
typedef union tree_node TYPE;
@@ -126,6 +125,7 @@ struct Dsymbol : Object
#endif
unsigned char *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Scope *scope; // !=NULL means context to use for semantic()
Dsymbol();
Dsymbol(Identifier *);
@@ -151,6 +151,7 @@ struct Dsymbol : Object
virtual const char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
virtual void setScope(Scope *sc);
virtual void semantic(Scope *sc);
virtual void semantic2(Scope *sc);
virtual void semantic3(Scope *sc);
@@ -245,7 +246,9 @@ struct Dsymbol : Object
virtual OverloadSet *isOverloadSet() { return NULL; }
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
#if TARGET_NET
virtual PragmaScope* isPragmaScope() { return NULL; }
#endif
#if IN_LLVM
/// Codegen traversal
virtual void codegen(Ir* ir);

View File

@@ -33,7 +33,6 @@ EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
#if IN_DMD
sinit = NULL;
#endif
scope = NULL;
isdeprecated = 0;
}

View File

@@ -40,8 +40,6 @@ struct EnumDeclaration : ScopeDsymbol
Expression *maxval;
Expression *minval;
Expression *defaultval; // default initializer
Scope *scope; // !=NULL means context to use
#endif
int isdeprecated;

View File

@@ -380,6 +380,11 @@ Expression *resolveProperties(Scope *sc, Expression *e)
}
}
else if (e->op == TOKdottd)
{
e = new CallExp(e->loc, e);
e = e->semantic(sc);
}
return e;
}
@@ -1002,7 +1007,7 @@ void Expression::rvalue()
dump(0);
halt();
#endif
type = Type::tint32;
type = Type::terror;
}
}
@@ -1064,6 +1069,9 @@ void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
void Expression::toMangleBuffer(OutBuffer *buf)
{
error("expression %s is not a valid template value argument", toChars());
#ifdef DEBUG
dump(0);
#endif
}
/***************************************
@@ -1116,6 +1124,7 @@ void Expression::checkScalar()
{
if (!type->isscalar())
error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
rvalue();
}
void Expression::checkNoBool()
@@ -1130,6 +1139,7 @@ Expression *Expression::checkIntegral()
{ error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
return new ErrorExp();
}
rvalue();
return this;
}
@@ -1139,6 +1149,7 @@ Expression *Expression::checkArithmetic()
{ error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
return new ErrorExp();
}
rvalue();
return this;
}
@@ -1996,6 +2007,28 @@ Expression *IdentifierExp::semantic(Scope *sc)
withsym = scopesym->isWithScopeSymbol();
if (withsym)
{
#if DMDV2
/* Disallow shadowing
*/
// First find the scope of the with
Scope *scwith = sc;
while (scwith->scopesym != scopesym)
{ scwith = scwith->enclosing;
assert(scwith);
}
// Look at enclosing scopes for symbols with the same name,
// in the same function
for (Scope *scx = scwith; scx && scx->func == scwith->func; scx = scx->enclosing)
{ Dsymbol *s2;
if (scx->scopesym && scx->scopesym->symtab &&
(s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL &&
s != s2)
{
error("with symbol %s is shadowing local symbol %s", s->toPrettyChars(), s2->toPrettyChars());
}
}
#endif
s = s->toAlias();
// Same as wthis.ident
@@ -2160,7 +2193,7 @@ Lagain:
if (!type)
{ type = v->type;
if (!v->type)
{ error("forward reference of %s", v->toChars());
{ error("forward reference of %s %s", v->kind(), v->toChars());
type = Type::terror;
}
}
@@ -2178,6 +2211,11 @@ Lagain:
f = s->isFuncDeclaration();
if (f)
{ //printf("'%s' is a function\n", f->toChars());
if (!f->type->deco)
{
error("forward reference to %s", toChars());
}
return new VarExp(loc, f, hasOverloads);
}
o = s->isOverloadSet();
@@ -2237,7 +2275,7 @@ Lagain:
TemplateInstance *ti = s->isTemplateInstance();
if (ti && !global.errors)
{ if (!ti->semanticdone)
{ if (!ti->semanticRun)
ti->semantic(sc);
s = ti->inst->toAlias();
if (!s->isTemplateInstance())
@@ -2926,6 +2964,7 @@ Expression *ArrayLiteralExp::semantic(Scope *sc)
for (int i = 0; i < elements->dim; i++)
{ e = (Expression *)elements->data[i];
e = e->semantic(sc);
assert(e->type);
elements->data[i] = (void *)e;
}
expandTuples(elements);
@@ -3405,6 +3444,11 @@ Expression *TypeExp::semantic(Scope *sc)
return this;
}
void TypeExp::rvalue()
{
error("type %s has no value", toChars());
}
void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
type->toCBuffer(buf, NULL, hgs);
@@ -3440,7 +3484,7 @@ Lagain:
ti = sds->isTemplateInstance();
if (ti && !global.errors)
{ Dsymbol *s;
if (!ti->semanticdone)
if (!ti->semanticRun)
ti->semantic(sc);
s = ti->inst->toAlias();
sds2 = s->isScopeDsymbol();
@@ -3655,7 +3699,26 @@ Lagain:
}
#endif
}
else if (fdn) // Possible problems here, no obvious solution when merging
#if 1
else if (thisexp)
error("e.new is only for allocating nested classes");
else if (fdn)
{
// make sure the parent context fdn of cd is reachable from sc
for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
{
if (fdn == sp)
break;
FuncDeclaration *fsp = sp ? sp->isFuncDeclaration() : NULL;
if (!sp || (fsp && fsp->isStatic()))
{
error("outer function context of %s is needed to 'new' nested class %s", fdn->toPrettyChars(), cd->toPrettyChars());
break;
}
}
}
#else
else if (fdn)
{ /* The nested class cd is nested inside a function,
* we'll let getEthis() look for errors.
*/
@@ -3664,6 +3727,7 @@ Lagain:
// Because thisexp cannot be a function frame pointer
error("e.new is only for allocating nested classes");
}
#endif
else
assert(0);
}
@@ -4028,6 +4092,7 @@ Expression *VarExp::semantic(Scope *sc)
}
#endif
}
/* Fix for 1161 doesn't work because it causes protection
* problems when instantiating imported templates passing private
* variables as alias template parameters.
@@ -4109,6 +4174,7 @@ Expression *VarExp::semantic(Scope *sc)
return e;
}
#endif
return this;
}
@@ -4295,6 +4361,7 @@ Expression *TupleExp::semantic(Scope *sc)
return (Expression *)exps->data[0];
}
type = new TypeTuple(exps);
type = type->semantic(loc, sc);
//printf("-TupleExp::semantic(%s)\n", toChars());
return this;
}
@@ -6159,7 +6226,7 @@ Expression *CallExp::semantic(Scope *sc)
if (e1->op == TOKimport && !e1->type)
{ ScopeExp *se = (ScopeExp *)e1;
TemplateInstance *ti = se->sds->isTemplateInstance();
if (ti && !ti->semanticdone)
if (ti && !ti->semanticRun)
{
/* Attempt to instantiate ti. If that works, go with it.
* If not, go with partial explicit specialization.
@@ -6187,7 +6254,7 @@ Expression *CallExp::semantic(Scope *sc)
if (e1->op == TOKdotti && !e1->type)
{ DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
TemplateInstance *ti = se->ti;
if (!ti->semanticdone)
if (!ti->semanticRun)
{
/* Attempt to instantiate ti. If that works, go with it.
* If not, go with partial explicit specialization.
@@ -6795,7 +6862,9 @@ void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
AddrExp::AddrExp(Loc loc, Expression *e)
: UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
{
#if IN_LLVM
m = NULL;
#endif
}
Expression *AddrExp::semantic(Scope *sc)
@@ -6805,15 +6874,30 @@ Expression *AddrExp::semantic(Scope *sc)
#endif
if (!type)
{
#if IN_LLVM
m = sc->module;
#endif
UnaExp::semantic(sc);
e1 = e1->toLvalue(sc, NULL);
if (!e1->type)
{
error("cannot take address of %s", e1->toChars());
type = Type::tint32;
return this;
return new ErrorExp();
}
if (!e1->type->deco)
{
/* No deco means semantic() was not run on the type.
* We have to run semantic() on the symbol to get the right type:
* auto x = &bar;
* pure: int bar() { return 1;}
* otherwise the 'pure' is missing from the type assigned to x.
*/
error("forward reference to %s", e1->toChars());
return new ErrorExp();
}
//printf("test3 deco = %p\n", e1->type->deco);
type = e1->type->pointerTo();
// See if this should really be a delegate
@@ -6878,8 +6962,8 @@ Expression *AddrExp::semantic(Scope *sc)
PtrExp::PtrExp(Loc loc, Expression *e)
: UnaExp(loc, TOKstar, sizeof(PtrExp), e)
{
if (e->type)
type = ((TypePointer *)e->type)->next;
// if (e->type)
// type = ((TypePointer *)e->type)->next;
}
PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
@@ -6889,8 +6973,7 @@ PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
}
Expression *PtrExp::semantic(Scope *sc)
{ Type *tb;
{
#if LOGSEMANTIC
printf("PtrExp::semantic('%s')\n", toChars());
#endif
@@ -6903,7 +6986,7 @@ Expression *PtrExp::semantic(Scope *sc)
Expression *e = op_overload(sc);
if (e)
return e;
tb = e1->type->toBasetype();
Type *tb = e1->type->toBasetype();
switch (tb->ty)
{
case Tpointer:
@@ -6918,8 +7001,7 @@ Expression *PtrExp::semantic(Scope *sc)
default:
error("can only * a pointer, not a '%s'", e1->type->toChars());
type = Type::tint32;
break;
return new ErrorExp();
}
rvalue();
}
@@ -9744,8 +9826,11 @@ Expression *CmpExp::semantic(Scope *sc)
}
#endif
else
{ e1->rvalue();
e2->rvalue();
e = this;
//printf("CmpExp: %s\n", e->toChars());
}
//printf("CmpExp: %s, type = %s\n", e->toChars(), e->type->toChars());
return e;
}

View File

@@ -85,6 +85,11 @@ FuncDeclaration *hasThis(Scope *sc);
Expression *fromConstInitializer(int result, Expression *e);
int arrayExpressionCanThrow(Expressions *exps);
struct IntRange
{ uinteger_t imin;
uinteger_t imax;
};
struct Expression : Object
{
Loc loc; // file location
@@ -122,6 +127,7 @@ struct Expression : Object
virtual Expression *modifiableLvalue(Scope *sc, Expression *e);
virtual Expression *implicitCastTo(Scope *sc, Type *t);
virtual MATCH implicitConvTo(Type *t);
virtual IntRange getIntRange();
virtual Expression *castTo(Scope *sc, Type *t);
virtual void checkEscape();
void checkScalar();
@@ -191,6 +197,7 @@ struct IntegerExp : Expression
Expression *interpret(InterState *istate);
char *toChars();
void dump(int indent);
IntRange getIntRange();
dinteger_t toInteger();
real_t toReal();
real_t toImaginary();
@@ -558,6 +565,7 @@ struct TypeExp : Expression
TypeExp(Loc loc, Type *type);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
void rvalue();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result);
#if IN_DMD
@@ -1230,6 +1238,8 @@ struct CastExp : UnaExp
CastExp(Loc loc, Expression *e, unsigned mod);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
MATCH implicitConvTo(Type *t);
IntRange getIntRange();
Expression *optimize(int result);
Expression *interpret(InterState *istate);
int checkSideEffect(int flag);
@@ -1334,11 +1344,14 @@ struct CommaExp : BinExp
CommaExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
void checkEscape();
IntRange getIntRange();
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
int isBool(int result);
int checkSideEffect(int flag);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
#if IN_DMD
@@ -1552,6 +1565,7 @@ struct DivExp : BinExp
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
@@ -1594,6 +1608,7 @@ struct ShlExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
@@ -1614,6 +1629,7 @@ struct ShrExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
@@ -1634,6 +1650,7 @@ struct UshrExp : BinExp
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate);
IntRange getIntRange();
// For operator overloading
Identifier *opId();
@@ -1656,6 +1673,7 @@ struct AndExp : BinExp
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
IntRange getIntRange();
// For operator overloading
int isCommutative();
@@ -1679,6 +1697,8 @@ struct OrExp : BinExp
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
MATCH implicitConvTo(Type *t);
IntRange getIntRange();
// For operator overloading
int isCommutative();
@@ -1702,6 +1722,8 @@ struct XorExp : BinExp
Expression *interpret(InterState *istate);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
MATCH implicitConvTo(Type *t);
IntRange getIntRange();
// For operator overloading
int isCommutative();

View File

@@ -1,5 +1,5 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -64,6 +64,9 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC s
inlineAsm = 0;
cantInterpret = 0;
semanticRun = 0;
#if DMDV1
nestedFrameRef = 0;
#endif
fes = NULL;
introducing = 0;
tintro = NULL;
@@ -71,17 +74,16 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC s
* NULL for the return type.
*/
inferRetType = (type && type->nextOf() == NULL);
scope = NULL;
hasReturnExp = 0;
nrvo_can = 1;
nrvo_var = NULL;
#if IN_DMD
shidden = NULL;
#endif
#if DMDV2
builtin = BUILTINunknown;
tookAddressOf = 0;
#endif
#if IN_LLVM
// LDC
isArrayOp = false;
@@ -125,8 +127,9 @@ Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
f->fbody = fbody ? fbody->syntaxCopy() : NULL;
assert(!fthrows); // deprecated
// LDC
#if IN_LLVM
f->intrinsicName = intrinsicName;
#endif
return f;
}
@@ -166,7 +169,7 @@ void FuncDeclaration::semantic(Scope *sc)
if (!originalType)
originalType = type;
if (!type->deco && type->nextOf())
if (!type->deco)
{
/* Apply const and invariant storage class
* to the function type
@@ -304,7 +307,9 @@ void FuncDeclaration::semantic(Scope *sc)
storage_class |= STCabstract;
if (isCtorDeclaration() ||
#if DMDV2
isPostBlitDeclaration() ||
#endif
isDtorDeclaration() ||
isInvariantDeclaration() ||
isUnitTestDeclaration() || isNewDeclaration() || isDelete())
@@ -878,6 +883,7 @@ void FuncDeclaration::semantic3(Scope *sc)
for (size_t i = 0; i < f->parameters->dim; i++)
{ Argument *arg = (Argument *)f->parameters->data[i];
//printf("[%d] arg->type->ty = %d %s\n", i, arg->type->ty, arg->type->toChars());
if (arg->type->ty == Ttuple)
{ TypeTuple *t = (TypeTuple *)arg->type;
size_t dim = Argument::dim(t->arguments);
@@ -1008,6 +1014,12 @@ void FuncDeclaration::semantic3(Scope *sc)
v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
v->noauto = 1;
#if DMDV2
if (f->isref)
{
v->storage_class |= STCref | STCforeach;
}
#endif
sc2->incontract--;
v->semantic(sc2);
sc2->incontract++;
@@ -1108,6 +1120,8 @@ void FuncDeclaration::semantic3(Scope *sc)
nrvo_can = 0;
fbody = fbody->semantic(sc2);
if (!fbody)
fbody = new CompoundStatement(0, new Statements());
if (inferRetType)
{ // If no return type inferred yet, then infer a void
@@ -1185,7 +1199,7 @@ void FuncDeclaration::semantic3(Scope *sc)
error("expected to return a value of type %s", type->nextOf()->toChars());
else if (!inlineAsm)
{
int blockexit = fbody ? fbody->blockExit() : 0;
int blockexit = fbody ? fbody->blockExit() : BEfallthru;
if (f->isnothrow && blockexit & BEthrow)
error("'%s' is nothrow yet may throw", toChars());
@@ -1204,7 +1218,8 @@ void FuncDeclaration::semantic3(Scope *sc)
if (offend)
{ Expression *e;
warning(loc, "no return at end of function");
//warning(loc, "no return exp; or assert(0); at end of function");
error("no return exp; or assert(0); at end of function");
if (global.params.useAssert &&
!global.params.useInline)
@@ -2169,16 +2184,22 @@ void FuncDeclaration::appendExp(Expression *e)
}
void FuncDeclaration::appendState(Statement *s)
{ CompoundStatement *cs;
{
if (!fbody)
{ Statements *a;
a = new Statements();
fbody = new CompoundStatement(0, a);
fbody = s;
else
{
CompoundStatement *cs = fbody->isCompoundStatement();
if (cs)
{
if (!cs->statements)
fbody = s;
else
cs->statements->push(s);
}
else
fbody = new CompoundStatement(0, fbody, s);
}
cs = fbody->isCompoundStatement();
cs->statements->push(s);
}
@@ -2635,6 +2656,7 @@ void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
/********************************* PostBlitDeclaration ****************************/
#if DMDV2
PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc)
: FuncDeclaration(loc, endloc, Id::_postblit, STCundefined, NULL)
{
@@ -2704,6 +2726,7 @@ void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring("=this()");
bodyToCBuffer(buf, hgs);
}
#endif
/********************************* DtorDeclaration ****************************/

View File

@@ -21,6 +21,7 @@
#include "mtype.h"
#include "declaration.h"
#include "id.h"
#include "attrib.h"
/********************************* Import ****************************/
@@ -100,10 +101,14 @@ void Import::load(Scope *sc)
s = dst->lookup(id);
if (s)
{
#if TARGET_NET
mod = (Module *)s;
#else
if (s->isModule())
mod = (Module *)s;
else
error("package and module have the same name");
#endif
}
if (!mod)
@@ -121,27 +126,25 @@ void Import::load(Scope *sc)
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
}
#if IN_LLVM
char* escapePath(char* fname, char* buffer, int bufLen) {
char* res = buffer;
bufLen -= 2; // for \0 and an occasional escape char
int dst = 0;
for (; dst < bufLen && *fname; ++dst, ++fname) {
switch (*fname) {
void escapePath(OutBuffer *buf, const char *fname)
{
while (1)
{
switch (*fname)
{
case 0:
return;
case '(':
case ')':
case '\\':
buffer[dst++] = '\\';
// fall through
buf->writebyte('\\');
default:
buffer[dst] = *fname;
buf->writebyte(*fname);
break;
}
fname++;
}
buffer[dst] = '\0';
return buffer;
}
#endif
void Import::semantic(Scope *sc)
{
@@ -165,8 +168,6 @@ void Import::semantic(Scope *sc)
//printf("%s imports %s\n", sc->module->toChars(), mod->toChars());
sc->module->aimports.push(mod);
mod->semantic();
if (!isstatic && !aliasId && !names.dim)
{
/* Default to private importing
@@ -177,6 +178,8 @@ void Import::semantic(Scope *sc)
sc->scopesym->importScope(mod, prot);
}
mod->semantic();
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
@@ -193,69 +196,77 @@ void Import::semantic(Scope *sc)
}
sc = sc->pop();
}
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
if (global.params.moduleDeps != NULL)
{
/* The grammar of the file is:
* ImportDeclaration
* ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
* ModuleAliasIdentifier ] "\n"
*
* BasicImportDeclaration
* ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection
* " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
*
* FilePath
* - any string with '(', ')' and '\' escaped with the '\' character
*/
if (global.params.moduleDeps != NULL) {
char fnameBuf[262]; // MAX_PATH+2
OutBuffer *ob = global.params.moduleDeps;
OutBuffer *const ob = global.params.moduleDeps;
ob->printf("%s (%s) : ",
sc->module->toPrettyChars(),
escapePath(sc->module->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf))
);
ob->writestring(sc->module->toPrettyChars());
ob->writestring(" (");
escapePath(ob, sc->module->srcfile->toChars());
ob->writestring(") : ");
char* protStr = "";
switch (sc->protection) {
case PROTpublic: protStr = "public"; break;
case PROTprivate: protStr = "private"; break;
case PROTpackage: protStr = "package"; break;
default: break;
}
ob->writestring(protStr);
if (isstatic) {
ob->writestring(" static");
}
ob->writestring(" : ");
ProtDeclaration::protectionToCBuffer(ob, sc->protection);
if (isstatic)
StorageClassDeclaration::stcToCBuffer(ob, STCstatic);
ob->writestring(": ");
if (this->packages) {
for (size_t i = 0; i < this->packages->dim; i++) {
Identifier *pid = (Identifier *)this->packages->data[i];
if (packages)
{
for (size_t i = 0; i < packages->dim; i++)
{
Identifier *pid = (Identifier *)packages->data[i];
ob->printf("%s.", pid->toChars());
}
}
ob->printf("%s (%s)",
this->id->toChars(),
mod ? escapePath(mod->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf)) : "???"
);
ob->writestring(id->toChars());
ob->writestring(" (");
if (mod)
escapePath(ob, mod->srcfile->toChars());
else
ob->writestring("???");
ob->writebyte(')');
if (aliasId) {
ob->printf(" -> %s", aliasId->toChars());
} else {
if (names.dim > 0) {
ob->writestring(" : ");
for (size_t i = 0; i < names.dim; i++)
{
if (i > 0) {
ob->writebyte(',');
}
for (size_t i = 0; i < names.dim; i++)
{
if (i == 0)
ob->writebyte(':');
else
ob->writebyte(',');
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias) {
ob->printf("%s", name->toChars());
alias = name;
} else {
ob->printf("%s=%s", alias->toChars(), name->toChars());
}
}
if (!alias)
{
ob->printf("%s", name->toChars());
alias = name;
}
else
ob->printf("%s=%s", alias->toChars(), name->toChars());
}
if (aliasId)
ob->printf(" -> %s", aliasId->toChars());
ob->writenl();
}
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic2(Scope *sc)
@@ -347,27 +358,7 @@ void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->printf("%s.", pid->toChars());
}
}
buf->printf("%s", id->toChars());
if (names.dim > 0) {
buf->writebyte(':');
for (size_t i = 0; i < names.dim; i++)
{
if (i > 0) {
buf->writebyte(',');
}
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias) {
buf->printf("%s", name->toChars());
alias = name;
} else {
buf->printf("%s=%s", alias->toChars(), name->toChars());
}
}
}
buf->writebyte(';');
buf->printf("%s;", id->toChars());
buf->writenl();
}

View File

@@ -34,7 +34,9 @@ struct Import : Dsymbol
Identifier *id; // module Identifier
Identifier *aliasId;
int isstatic; // !=0 if static import
#if IN_LLVM
enum PROT protection;
#endif
// Pairs of alias=name to bind into current namespace
Array names;
@@ -50,7 +52,9 @@ struct Import : Dsymbol
void addAlias(Identifier *name, Identifier *alias);
const char *kind();
#if IN_LLVM
enum PROT prot();
#endif
Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
void load(Scope *sc);
void semantic(Scope *sc);

View File

@@ -15,6 +15,10 @@
#include <stdlib.h>
#include <ctype.h>
#if _WIN32
#include <windows.h>
#endif
#if __APPLE__
#include <sys/syslimits.h>
#endif
@@ -91,6 +95,15 @@ void inifile(const char *argv0x, const char *inifilex)
filename = FileName::combine(getenv("HOME"), inifile);
if (!FileName::exists(filename))
{
#if _WIN32 // This fix by Tim Matthews
char resolved_name[MAX_PATH + 1];
if(GetModuleFileName(NULL, resolved_name, MAX_PATH + 1) && FileName::exists(resolved_name))
{
filename = (char *)FileName::replaceName(resolved_name, inifile);
if(FileName::exists(filename))
goto Ldone;
}
#endif
filename = (char *)FileName::replaceName(argv0, inifile);
if (!FileName::exists(filename))
{

View File

@@ -396,24 +396,70 @@ Expression *ArrayInitializer::toExpression()
{ Expressions *elements;
Expression *e;
//printf("ArrayInitializer::toExpression()\n");
//printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
//static int i; if (++i == 2) halt();
size_t edim;
Type *t = NULL;
if (type)
{
t = type->toBasetype();
switch (t->ty)
{
case Tsarray:
edim = ((TypeSArray *)t)->dim->toInteger();
break;
case Tpointer:
case Tarray:
edim = dim;
break;
default:
assert(0);
}
}
else
edim = value.dim;
elements = new Expressions();
for (size_t i = 0; i < value.dim; i++)
elements->setDim(edim);
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{
if (index.data[i])
goto Lno;
j = ((Expression *)index.data[i])->toInteger();
assert(j < edim);
Initializer *iz = (Initializer *)value.data[i];
if (!iz)
goto Lno;
Expression *ex = iz->toExpression();
if (!ex)
{
goto Lno;
elements->push(ex);
}
elements->data[j] = ex;
}
e = new ArrayLiteralExp(loc, elements);
/* Fill in any missing elements with the default initializer
*/
{
Expression *init = NULL;
for (size_t i = 0; i < edim; i++)
{
if (!elements->data[i])
{
if (!type)
goto Lno;
if (!init)
init = ((TypeNext *)t)->next->defaultInit();
elements->data[i] = init;
}
}
Expression *e = new ArrayLiteralExp(loc, elements);
e->type = type;
return e;
}
Lno:
delete elements;
@@ -466,21 +512,26 @@ Lno:
Type *ArrayInitializer::inferType(Scope *sc)
{
//printf("ArrayInitializer::inferType() %s\n", toChars());
type = Type::terror;
for (size_t i = 0; i < value.dim; i++)
{
if (index.data[i])
goto Lno;
}
if (value.dim)
for (size_t i = 0; i < value.dim; i++)
{
Initializer *iz = (Initializer *)value.data[0];
Initializer *iz = (Initializer *)value.data[i];
if (iz)
{ Type *t = iz->inferType(sc);
t = new TypeSArray(t, new IntegerExp(value.dim));
t = t->semantic(loc, sc);
return t;
if (i == 0)
{ t = new TypeSArray(t, new IntegerExp(value.dim));
t = t->semantic(loc, sc);
type = t;
}
}
}
return type;
Lno:
error(loc, "cannot infer type from this array initializer");

View File

@@ -2293,6 +2293,8 @@ Expression *interpret_aaKeys(InterState *istate, Expressions *arguments)
return NULL;
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
Expression *e = new ArrayLiteralExp(aae->loc, aae->keys);
Type *elemType = ((TypeAArray *)aae->type)->index;
e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0));
return e;
}
@@ -2309,6 +2311,8 @@ Expression *interpret_aaValues(InterState *istate, Expressions *arguments)
return NULL;
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
Expression *e = new ArrayLiteralExp(aae->loc, aae->values);
Type *elemType = ((TypeAArray *)aae->type)->next;
e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0));
//printf("result is %s\n", e->toChars());
return e;
}

View File

@@ -1278,7 +1278,9 @@ unsigned Lexer::escapeSequence()
}
}
if (ndigits != 2 && !utf_isValidDchar(v))
error("invalid UTF character \\U%08x", v);
{ error("invalid UTF character \\U%08x", v);
v = '?'; // recover with valid UTF character
}
c = v;
}
else

View File

@@ -113,9 +113,9 @@ char *Declaration::mangle()
case LINKd:
break;
// LDC
#if IN_LLVM
case LINKintrinsic:
#endif
case LINKc:
case LINKwindows:
case LINKpascal:

View File

@@ -98,7 +98,7 @@ Global::Global()
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
#endif
;
version = "v2.030";
version = "v2.031";
#if IN_LLVM
ldc_version = LDC_REV;
llvm_version = LLVM_REV_STR;

View File

@@ -209,10 +209,10 @@ struct Param
Array *debuglibnames; // default libraries for debug builds
const char *xmlname; // filename for XML output
OutBuffer *moduleDeps; // buffer and filename for emitting module deps
char *moduleDepsFile;
char *moduleDepsFile; // filename for deps output
OutBuffer *moduleDeps; // contents to be written to deps file
// Hidden debug switches
bool debuga;
bool debugb;
@@ -443,7 +443,7 @@ void util_progress();
#if IN_GCC || IN_LLVM
#define stdmsg stderr
#else
#define stdmsg stdout
#define stdmsg stderr
#endif
#if !IN_LLVM

View File

@@ -99,7 +99,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
searchCacheSymbol = NULL;
searchCacheFlags = 0;
semanticstarted = 0;
semanticdone = 0;
semanticRun = 0;
decldefs = NULL;
vmoduleinfo = NULL;
#if IN_DMD
@@ -770,25 +770,32 @@ void Module::semantic(Scope* unused_sc)
// Add all symbols into module's symbol table
symtab = new DsymbolTable();
for (i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
{ Dsymbol *s = (Dsymbol *)members->data[i];
s->addMember(NULL, sc->scopesym, 1);
}
/* Set scope for the symbols so that if we forward reference
* a symbol, it can possibly be resolved on the spot.
* If this works out well, it can be extended to all modules
* before any semantic() on any of them.
*/
for (i = 0; i < members->dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i];
s->setScope(sc);
}
// Pass 1 semantic routines: do public side of the definition
for (i = 0; i < members->dim; i++)
{ Dsymbol *s;
{ Dsymbol *s = (Dsymbol *)members->data[i];
s = (Dsymbol *)members->data[i];
//printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
s->semantic(sc);
runDeferredSemantic();
}
sc = sc->pop();
sc->pop();
semanticdone = semanticstarted;
sc->pop(); // 2 pops because Scope::createGlobal() created 2
semanticRun = semanticstarted;
//printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
}
@@ -827,7 +834,7 @@ void Module::semantic2(Scope* unused_sc)
sc = sc->pop();
sc->pop();
semanticdone = semanticstarted;
semanticRun = semanticstarted;
//printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
}
@@ -857,7 +864,7 @@ void Module::semantic3(Scope* unused_sc)
sc = sc->pop();
sc->pop();
semanticdone = semanticstarted;
semanticRun = semanticstarted;
}
void Module::inlineScan()
@@ -882,7 +889,7 @@ void Module::inlineScan()
s->inlineScan();
}
semanticdone = semanticstarted;
semanticRun = semanticstarted;
}
/****************************************************
@@ -1143,11 +1150,14 @@ DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppk
else
{
assert(p->isPackage());
#if TARGET_NET //dot net needs modules and packages with same name
#else
if (p->isModule())
{ p->error("module and package have the same name");
fatal();
break;
}
#endif
}
parent = p;
dst = ((Package *)p)->symtab;

View File

@@ -91,7 +91,7 @@ struct Module : Package
int searchCacheFlags; // cached flags
int semanticstarted; // has semantic() been started?
int semanticdone; // has semantic() been done?
int semanticRun; // has semantic() been done?
int root; // != 0 if this is a 'root' module,
// i.e. a module that will be taken all the
// way to an object file

View File

@@ -1171,6 +1171,10 @@ Type *Type::merge()
sv = stringtable.update((char *)buf.data, buf.offset);
if (sv->ptrvalue)
{ t = (Type *) sv->ptrvalue;
#ifdef DEBUG
if (!t->deco)
printf("t = %s\n", t->toChars());
#endif
assert(t->deco);
//printf("old value, deco = '%s' %p\n", t->deco, t->deco);
}
@@ -1324,14 +1328,14 @@ int Type::isBaseOf(Type *t, int *poffset)
* Determine if 'this' can be implicitly converted
* to type 'to'.
* Returns:
* 0 can't convert
* 1 can convert using implicit conversions
* 2 this and to are the same type
* MATCHnomatch, MATCHconvert, MATCHconst, MATCHexact
*/
MATCH Type::implicitConvTo(Type *to)
{
//printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to);
//printf("from: %s\n", toChars());
//printf("to : %s\n", to->toChars());
if (this == to)
return MATCHexact;
return MATCHnomatch;
@@ -1591,6 +1595,33 @@ Type *Type::nextOf()
return NULL;
}
/****************************************
* Return the mask that an integral type will
* fit into.
*/
uinteger_t Type::sizemask()
{ uinteger_t m;
switch (toBasetype()->ty)
{
case Tbool: m = 1; break;
case Tchar:
case Tint8:
case Tuns8: m = 0xFF; break;
case Twchar:
case Tint16:
case Tuns16: m = 0xFFFFUL; break;
case Tdchar:
case Tint32:
case Tuns32: m = 0xFFFFFFFFUL; break;
case Tint64:
case Tuns64: m = 0xFFFFFFFFFFFFFFFFULL; break;
default:
assert(0);
}
return m;
}
/* ============================= TypeNext =========================== */
TypeNext::TypeNext(TY ty, Type *next)
@@ -1610,7 +1641,8 @@ void TypeNext::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
void TypeNext::checkDeprecated(Loc loc, Scope *sc)
{
Type::checkDeprecated(loc, sc);
next->checkDeprecated(loc, sc);
if (next) // next can be NULL if TypeFunction and auto return type
next->checkDeprecated(loc, sc);
}
@@ -1632,7 +1664,8 @@ Type *TypeNext::makeConst()
return cto;
}
TypeNext *t = (TypeNext *)Type::makeConst();
if (ty != Tfunction && ty != Tdelegate && next->deco &&
if (ty != Tfunction && ty != Tdelegate &&
(next->deco || next->ty == Tfunction) &&
!next->isInvariant() && !next->isConst())
{ if (next->isShared())
t->next = next->sharedConstOf();
@@ -1651,7 +1684,8 @@ Type *TypeNext::makeInvariant()
return ito;
}
TypeNext *t = (TypeNext *)Type::makeInvariant();
if (ty != Tfunction && ty != Tdelegate && next->deco &&
if (ty != Tfunction && ty != Tdelegate &&
(next->deco || next->ty == Tfunction) &&
!next->isInvariant())
{ t->next = next->invariantOf();
}
@@ -1666,7 +1700,8 @@ Type *TypeNext::makeShared()
return sto;
}
TypeNext *t = (TypeNext *)Type::makeShared();
if (ty != Tfunction && ty != Tdelegate && next->deco &&
if (ty != Tfunction && ty != Tdelegate &&
(next->deco || next->ty == Tfunction) &&
!next->isInvariant() && !next->isShared())
{
if (next->isConst())
@@ -1686,7 +1721,8 @@ Type *TypeNext::makeSharedConst()
return scto;
}
TypeNext *t = (TypeNext *)Type::makeSharedConst();
if (ty != Tfunction && ty != Tdelegate && next->deco &&
if (ty != Tfunction && ty != Tdelegate &&
(next->deco || next->ty == Tfunction) &&
!next->isInvariant() && !next->isSharedConst())
{
t->next = next->sharedConstOf();
@@ -2361,23 +2397,17 @@ MATCH TypeBasic::implicitConvTo(Type *to)
if (this == to)
return MATCHexact;
#if DMDV2
if (ty == to->ty)
{
return (mod == to->mod) ? MATCHexact : MATCHconst;
}
#endif
if (ty == Tvoid || to->ty == Tvoid)
return MATCHnomatch;
if (1 || global.params.Dversion == 1)
{
if (to->ty == Tbool)
return MATCHnomatch;
}
else
{
if (ty == Tbool || to->ty == Tbool)
return MATCHnomatch;
}
if (to->ty == Tbool)
return MATCHnomatch;
if (!to->isTypeBasic())
return MATCHnomatch;
@@ -2388,19 +2418,23 @@ MATCH TypeBasic::implicitConvTo(Type *to)
if (tob->flags & (TFLAGSimaginary | TFLAGScomplex))
return MATCHnomatch;
// If converting to integral
if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral)
#if DMDV2
// If converting from integral to integral
if (1 && tob->flags & TFLAGSintegral)
{ d_uns64 sz = size(0);
d_uns64 tosz = tob->size(0);
/* Can't convert to smaller size or, if same size, change sign
/* Can't convert to smaller size
*/
if (sz > tosz)
return MATCHnomatch;
/* Can't change sign if same size
*/
/*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
return MATCHnomatch;*/
}
#endif
}
else if (flags & TFLAGSfloating)
{
@@ -3552,6 +3586,8 @@ Type *TypePointer::syntaxCopy()
Type *TypePointer::semantic(Loc loc, Scope *sc)
{
//printf("TypePointer::semantic()\n");
if (deco)
return this;
Type *n = next->semantic(loc, sc);
switch (n->toBasetype()->ty)
{
@@ -3561,7 +3597,9 @@ Type *TypePointer::semantic(Loc loc, Scope *sc)
break;
}
if (n != next)
{
deco = NULL;
}
next = n;
transitive();
return merge();
@@ -3801,7 +3839,13 @@ int Type::covariant(Type *t)
Argument *arg2 = Argument::getNth(t2->parameters, i);
if (!arg1->type->equals(arg2->type))
goto Ldistinct;
{
#if 0 // turn on this for contravariant argument types, see bugzilla 3075
// We can add const, but not subtract it
if (arg2->type->implicitConvTo(arg1->type) < MATCHconst)
#endif
goto Ldistinct;
}
if ((arg1->storageClass & ~STCscope) != (arg2->storageClass & ~STCscope))
inoutmismatch = 1;
// We can add scope, but not subtract it
@@ -4057,7 +4101,7 @@ void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
if (mod & MODconst)
buf->writestring(" const");
if (mod & MODinvariant)
buf->writestring(" invariant");
buf->writestring(" immutable");
if (mod & MODshared)
buf->writestring(" shared");
}
@@ -4081,6 +4125,10 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
//printf("TypeFunction::semantic() this = %p\n", this);
//printf("TypeFunction::semantic() %s, sc->stc = %x\n", toChars(), sc->stc);
/* Copy in order to not mess up original.
* This can produce redundant copies if inferring return type,
* as semantic() will get called again on this.
*/
TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
memcpy(tf, this, sizeof(TypeFunction));
if (parameters)
@@ -4101,26 +4149,24 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
tf->isref = TRUE;
tf->linkage = sc->linkage;
if (!tf->next)
if (tf->next)
{
assert(global.errors);
tf->next = tvoid;
tf->next = tf->next->semantic(loc,sc);
if (tf->next->toBasetype()->ty == Tsarray)
{ error(loc, "functions cannot return static array %s", tf->next->toChars());
tf->next = Type::terror;
}
if (tf->next->toBasetype()->ty == Tfunction)
{ error(loc, "functions cannot return a function");
tf->next = Type::terror;
}
if (tf->next->toBasetype()->ty == Ttuple)
{ error(loc, "functions cannot return a tuple");
tf->next = Type::terror;
}
if (tf->next->isauto() && !(sc->flags & SCOPEctor))
error(loc, "functions cannot return scope %s", tf->next->toChars());
}
tf->next = tf->next->semantic(loc,sc);
if (tf->next->toBasetype()->ty == Tsarray)
{ error(loc, "functions cannot return static array %s", tf->next->toChars());
tf->next = Type::terror;
}
if (tf->next->toBasetype()->ty == Tfunction)
{ error(loc, "functions cannot return a function");
tf->next = Type::terror;
}
if (tf->next->toBasetype()->ty == Ttuple)
{ error(loc, "functions cannot return a tuple");
tf->next = Type::terror;
}
if (tf->next->isauto() && !(sc->flags & SCOPEctor))
error(loc, "functions cannot return scope %s", tf->next->toChars());
if (tf->parameters)
{ size_t dim = Argument::dim(tf->parameters);
@@ -4168,7 +4214,8 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
}
}
}
tf->deco = tf->merge()->deco;
if (tf->next)
tf->deco = tf->merge()->deco;
if (tf->inuse)
{ error(loc, "recursive type");
@@ -4770,11 +4817,11 @@ void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
*/
void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
{ Dsymbol *s;
{
Dsymbol *scopesym;
//printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
s = sc->search(loc, ident, &scopesym);
Dsymbol *s = sc->search(loc, ident, &scopesym);
resolveHelper(loc, sc, s, scopesym, pe, pt, ps);
if (*pt)
(*pt) = (*pt)->addMod(mod);
@@ -5241,7 +5288,7 @@ Type *TypeEnum::syntaxCopy()
Type *TypeEnum::semantic(Loc loc, Scope *sc)
{
//printf("TypeEnum::semantic() %s\n", toChars());
sym->semantic(sc);
//sym->semantic(sc);
return merge();
}
@@ -5895,7 +5942,7 @@ L1:
TemplateInstance *ti = s->isTemplateInstance();
if (ti)
{ if (!ti->semanticdone)
{ if (!ti->semanticRun)
ti->semantic(sc);
s = ti->inst->toAlias();
if (!s->isTemplateInstance())
@@ -6134,8 +6181,9 @@ Type *TypeClass::syntaxCopy()
Type *TypeClass::semantic(Loc loc, Scope *sc)
{
//printf("TypeClass::semantic(%s)\n", sym->toChars());
if (sym->scope)
sym->semantic(sym->scope);
if (deco)
return this;
//printf("\t%s\n", merge()->deco);
return merge();
}
@@ -6426,7 +6474,7 @@ L1:
TemplateInstance *ti = s->isTemplateInstance();
if (ti)
{ if (!ti->semanticdone)
{ if (!ti->semanticRun)
ti->semantic(sc);
s = ti->inst->toAlias();
if (!s->isTemplateInstance())

View File

@@ -306,6 +306,8 @@ struct Type : Object
virtual int hasPointers();
//Type *next;
virtual Type *nextOf();
uinteger_t sizemask();
static void error(Loc loc, const char *format, ...) IS_PRINTF(2);
static void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
@@ -714,10 +716,10 @@ struct TypeEnum : Type
EnumDeclaration *sym;
TypeEnum(EnumDeclaration *sym);
Type *syntaxCopy();
d_uns64 size(Loc loc);
unsigned alignsize();
char *toChars();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);

View File

@@ -198,6 +198,7 @@ Expression *UnaExp::op_overload(Scope *sc)
}
}
#if DMDV2
// Didn't find it. Forward to aliasthis
if (ad->aliasthis)
{
@@ -210,6 +211,7 @@ Expression *UnaExp::op_overload(Scope *sc)
e = e->semantic(sc);
return e;
}
#endif
}
return NULL;
}
@@ -441,6 +443,7 @@ Expression *BinExp::op_overload(Scope *sc)
}
}
#if DMDV2
// Try alias this on first operand
if (ad1 && ad1->aliasthis)
{
@@ -466,7 +469,7 @@ Expression *BinExp::op_overload(Scope *sc)
e = e->semantic(sc);
return e;
}
#endif
return NULL;
}

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -805,6 +805,16 @@ Expression *IndexExp::optimize(int result)
//printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
e1 = fromConstInitializer(result, e1);
if (this->e1->op == TOKvar)
{ VarExp *ve = (VarExp *)this->e1;
if (ve->var->storage_class & STCmanifest)
{ /* We generally don't want to have more than one copy of an
* array literal, but if it's an enum we have to because the
* enum isn't stored elsewhere. See Bugzilla 2559
*/
this->e1 = e1;
}
}
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
e = Index(type, e1, e2);
if (e == EXP_CANT_INTERPRET)

View File

@@ -3144,6 +3144,7 @@ Statement *Parser::parseStatement(int flags)
Condition *condition;
Statement *ifbody;
Statement *elsebody;
bool isfinal;
Loc loc = this->loc;
//printf("parseStatement()\n");
@@ -3245,13 +3246,21 @@ Statement *Parser::parseStatement(int flags)
goto Ldeclaration;
}
case TOKfinal:
if (peekNext() == TOKswitch)
{
nextToken();
isfinal = TRUE;
goto Lswitch;
}
goto Ldeclaration;
CASE_BASIC_TYPES:
case TOKtypedef:
case TOKalias:
case TOKconst:
case TOKauto:
case TOKextern:
case TOKfinal:
case TOKinvariant:
#if DMDV2
case TOKimmutable:
@@ -3651,15 +3660,17 @@ Statement *Parser::parseStatement(int flags)
}
case TOKswitch:
{ Expression *condition;
Statement *body;
isfinal = FALSE;
goto Lswitch;
Lswitch:
{
nextToken();
check(TOKlparen);
condition = parseExpression();
Expression *condition = parseExpression();
check(TOKrparen);
body = parseStatement(PSscope);
s = new SwitchStatement(loc, condition, body);
Statement *body = parseStatement(PSscope);
s = new SwitchStatement(loc, condition, body, isfinal);
break;
}
@@ -3667,6 +3678,7 @@ Statement *Parser::parseStatement(int flags)
{ Expression *exp;
Statements *statements;
Array cases; // array of Expression's
Expression *last = NULL;
while (1)
{
@@ -3678,6 +3690,20 @@ Statement *Parser::parseStatement(int flags)
}
check(TOKcolon);
#if DMDV2
/* case exp: .. case last:
*/
if (token.value == TOKslice)
{
if (cases.dim > 1)
error("only one case allowed for start of case range");
nextToken();
check(TOKcase);
last = parseAssignExp();
check(TOKcolon);
}
#endif
statements = new Statements();
while (token.value != TOKcase &&
token.value != TOKdefault &&
@@ -3688,11 +3714,20 @@ Statement *Parser::parseStatement(int flags)
s = new CompoundStatement(loc, statements);
s = new ScopeStatement(loc, s);
// Keep cases in order by building the case statements backwards
for (int i = cases.dim; i; i--)
#if DMDV2
if (last)
{
exp = (Expression *)cases.data[i - 1];
s = new CaseStatement(loc, exp, s);
s = new CaseRangeStatement(loc, exp, last, s);
}
else
#endif
{
// Keep cases in order by building the case statements backwards
for (int i = cases.dim; i; i--)
{
exp = (Expression *)cases.data[i - 1];
s = new CaseStatement(loc, exp, s);
}
}
break;
}
@@ -4024,6 +4059,8 @@ void Parser::check(enum TOK value, const char *string)
* needId 0 no identifier
* 1 identifier optional
* 2 must have identifier
* Output:
* if *pt is not NULL, it is set to the ending token, which would be endtok
*/
int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
@@ -4062,7 +4099,7 @@ int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
goto Lisnot;
Lis:
//printf("\tis declaration\n");
//printf("\tis declaration, t = %s\n", t->toChars());
return TRUE;
Lisnot:
@@ -4357,7 +4394,6 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
int Parser::isParameters(Token **pt)
{ // This code parallels parseParameters()
Token *t = *pt;
int tmp;
//printf("isParameters()\n");
if (t->value != TOKlparen)
@@ -4366,6 +4402,7 @@ int Parser::isParameters(Token **pt)
t = peek(t);
for (;1; t = peek(t))
{
L1:
switch (t->value)
{
case TOKrparen:
@@ -4380,12 +4417,23 @@ int Parser::isParameters(Token **pt)
case TOKinout:
case TOKref:
case TOKlazy:
case TOKfinal:
continue;
case TOKconst:
case TOKinvariant:
case TOKimmutable:
case TOKshared:
case TOKfinal:
continue;
t = peek(t);
if (t->value == TOKlparen)
{
t = peek(t);
if (!isDeclaration(t, 0, TOKrparen, &t))
return FALSE;
t = peek(t); // skip past closing ')'
goto L2;
}
goto L1;
#if 0
case TOKstatic:
@@ -4404,9 +4452,10 @@ int Parser::isParameters(Token **pt)
#endif
default:
if (!isBasicType(&t))
{ if (!isBasicType(&t))
return FALSE;
tmp = FALSE;
L2:
int tmp = FALSE;
if (t->value != TOKdotdotdot &&
!isDeclarator(&t, &tmp, TOKreserved))
return FALSE;
@@ -4420,6 +4469,7 @@ int Parser::isParameters(Token **pt)
t = peek(t);
break;
}
}
L3:
if (t->value == TOKcomma)
{

View File

@@ -61,21 +61,25 @@ void AsyncRead::addFile(File *file)
void AsyncRead::start()
{
unsigned threadaddr;
hThread = (HANDLE) _beginthreadex(NULL,
0,
&startthread,
this,
0,
(unsigned *)&threadaddr);
//printf("aw->filesdim = %p %d\n", this, filesdim);
if (filesdim)
{
unsigned threadaddr;
hThread = (HANDLE) _beginthreadex(NULL,
0,
&startthread,
this,
0,
(unsigned *)&threadaddr);
if (hThread)
{
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
}
else
{
assert(0);
if (hThread)
{
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
}
else
{
assert(0);
}
}
}
@@ -98,6 +102,7 @@ unsigned __stdcall startthread(void *p)
{
AsyncRead *aw = (AsyncRead *)p;
//printf("aw->filesdim = %p %d\n", aw, aw->filesdim);
for (size_t i = 0; i < aw->filesdim; i++)
{ FileData *f = &aw->files[i];

View File

@@ -71,6 +71,7 @@ Scope::Scope()
this->nofree = 0;
this->noctor = 0;
this->noaccesscheck = 0;
this->mustsemantic = 0;
this->intypeof = 0;
this->parameterSpecialization = 0;
this->callSuper = 0;
@@ -119,6 +120,7 @@ Scope::Scope(Scope *enclosing)
this->nofree = 0;
this->noctor = enclosing->noctor;
this->noaccesscheck = enclosing->noaccesscheck;
this->mustsemantic = enclosing->mustsemantic;
this->intypeof = enclosing->intypeof;
this->parameterSpecialization = enclosing->parameterSpecialization;
this->callSuper = enclosing->callSuper;

View File

@@ -71,6 +71,7 @@ struct Scope
int intypeof; // in typeof(exp)
int parameterSpecialization; // if in template parameter specialization
int noaccesscheck; // don't do access checks
int mustsemantic; // cannot defer semantic()
unsigned callSuper; // primitive flow analysis for constructors
#define CSXthis_ctor 1 // called this()

View File

@@ -144,6 +144,13 @@ int Statement::comeFrom()
return FALSE;
}
// Return TRUE if statement has no code in it
int Statement::isEmpty()
{
//printf("Statement::isEmpty()\n");
return FALSE;
}
/****************************************
* If this statement has code that needs to run in a finally clause
* at the end of the current scope, return that code in the form of
@@ -580,6 +587,16 @@ int CompoundStatement::comeFrom()
return comefrom;
}
int CompoundStatement::isEmpty()
{
for (int i = 0; i < statements->dim; i++)
{ Statement *s = (Statement *) statements->data[i];
if (s && !s->isEmpty())
return FALSE;
}
return TRUE;
}
/******************************** CompoundDeclarationStatement ***************************/
@@ -856,6 +873,12 @@ int ScopeStatement::comeFrom()
return statement ? statement->comeFrom() : FALSE;
}
int ScopeStatement::isEmpty()
{
//printf("ScopeStatement::isEmpty() %d\n", statement ? statement->isEmpty() : TRUE);
return statement ? statement->isEmpty() : TRUE;
}
void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writeByte('{');
@@ -1536,7 +1559,6 @@ Statement *ForeachStatement::semantic(Scope *sc)
/* Generate a temporary __r and initialize it with the aggregate.
*/
Identifier *id = Identifier::generateId("__r");
aggr = aggr->semantic(sc);
Expression *rinit = new SliceExp(loc, aggr, NULL, NULL);
rinit = rinit->trySemantic(sc);
if (!rinit) // if application of [] failed
@@ -1870,7 +1892,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
}
s = new CompoundStatement(loc, a);
s = new SwitchStatement(loc, e, s);
s = new SwitchStatement(loc, e, s, FALSE);
s = s->semantic(sc);
}
break;
@@ -2546,23 +2568,25 @@ void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
/******************************** SwitchStatement ***************************/
SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b)
SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal)
: Statement(loc)
{
condition = c;
body = b;
this->condition = c;
this->body = b;
this->isFinal = isFinal;
sdefault = NULL;
cases = NULL;
hasNoDefault = 0;
hasVars = 0;
// LDC
#if IN_LLVM
enclosingScopeExit = NULL;
#endif
}
Statement *SwitchStatement::syntaxCopy()
{
SwitchStatement *s = new SwitchStatement(loc,
condition->syntaxCopy(), body->syntaxCopy());
condition->syntaxCopy(), body->syntaxCopy(), isFinal);
return s;
}
@@ -2571,8 +2595,9 @@ Statement *SwitchStatement::semantic(Scope *sc)
//printf("SwitchStatement::semantic(%p)\n", this);
assert(!cases); // ensure semantic() is only run once
// LDC
#if IN_LLVM
enclosingScopeExit = sc->enclosingScopeExit;
#endif
condition = condition->semantic(sc);
condition = resolveProperties(sc, condition);
@@ -2663,6 +2688,37 @@ Statement *SwitchStatement::semantic(Scope *sc)
body = cs;
}
#if DMDV2
if (isFinal)
{ Type *t = condition->type;
while (t->ty == Ttypedef)
{ // Don't use toBasetype() because that will skip past enums
t = ((TypeTypedef *)t)->sym->basetype;
}
if (condition->type->ty == Tenum)
{ TypeEnum *te = (TypeEnum *)condition->type;
EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration();
assert(ed);
size_t dim = ed->members->dim;
for (size_t i = 0; i < dim; i++)
{
EnumMember *em = ((Dsymbol *)ed->members->data[i])->isEnumMember();
if (em)
{
for (size_t j = 0; j < cases->dim; j++)
{ CaseStatement *cs = (CaseStatement *)cases->data[j];
if (cs->exp->equals(em->value))
goto L1;
}
error("enum member %s not represented in final switch", em->toChars());
}
L1:
;
}
}
}
#endif
sc->pop();
return this;
}
@@ -2746,13 +2802,13 @@ Statement *CaseStatement::semantic(Scope *sc)
exp = exp->semantic(sc);
if (sw)
{
// LDC
#if IN_LLVM
enclosingScopeExit = sc->enclosingScopeExit;
if (enclosingScopeExit != sw->enclosingScopeExit)
{
error("case must be inside the same try, synchronized or volatile level as switch");
}
#endif
exp = exp->implicitCastTo(sc, sw->condition->type);
exp = exp->optimize(WANTvalue | WANTinterpret);
@@ -2767,6 +2823,8 @@ Statement *CaseStatement::semantic(Scope *sc)
* for this, i.e. generate a sequence of if-then-else
*/
sw->hasVars = 1;
if (sw->isFinal)
error("case variables not allowed in final switch statements");
goto L1;
}
}
@@ -2846,6 +2904,85 @@ void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
statement->toCBuffer(buf, hgs);
}
/******************************** CaseRangeStatement ***************************/
#if DMDV2
CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first,
Expression *last, Statement *s)
: Statement(loc)
{
this->first = first;
this->last = last;
this->statement = s;
}
Statement *CaseRangeStatement::syntaxCopy()
{
CaseRangeStatement *s = new CaseRangeStatement(loc,
first->syntaxCopy(), last->syntaxCopy(), statement->syntaxCopy());
return s;
}
Statement *CaseRangeStatement::semantic(Scope *sc)
{ SwitchStatement *sw = sc->sw;
//printf("CaseRangeStatement::semantic() %s\n", toChars());
if (sw->isFinal)
error("case ranges not allowed in final switch");
first = first->semantic(sc);
first = first->implicitCastTo(sc, sw->condition->type);
first = first->optimize(WANTvalue | WANTinterpret);
dinteger_t fval = first->toInteger();
last = last->semantic(sc);
last = last->implicitCastTo(sc, sw->condition->type);
last = last->optimize(WANTvalue | WANTinterpret);
dinteger_t lval = last->toInteger();
if (lval - fval > 256)
{ error("more than 256 cases in case range");
lval = fval + 256;
}
/* This works by replacing the CaseRange with an array of Case's.
*
* case a: .. case b: s;
* =>
* case a:
* [...]
* case b:
* s;
*/
Statements *statements = new Statements();
for (dinteger_t i = fval; i <= lval; i++)
{
Statement *s = statement;
if (i != lval)
s = new ExpStatement(loc, NULL);
Expression *e = new IntegerExp(loc, i, first->type);
Statement *cs = new CaseStatement(loc, e, s);
statements->push(cs);
}
Statement *s = new CompoundStatement(loc, statements);
s = s->semantic(sc);
return s;
}
void CaseRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("case ");
first->toCBuffer(buf, hgs);
buf->writestring(": .. case ");
last->toCBuffer(buf, hgs);
buf->writenl();
statement->toCBuffer(buf, hgs);
}
#endif
/******************************** DefaultStatement ***************************/
DefaultStatement::DefaultStatement(Loc loc, Statement *s)
@@ -2877,12 +3014,18 @@ Statement *DefaultStatement::semantic(Scope *sc)
}
sc->sw->sdefault = this;
// LDC
#if IN_LLVM
enclosingScopeExit = sc->enclosingScopeExit;
if (enclosingScopeExit != sc->sw->enclosingScopeExit)
{
error("default must be inside the same try, synchronized or volatile level as switch");
}
if (sc->sw->isFinal)
{
error("default statement not allowed in final switch statement");
}
#endif
}
else
error("default not in switch statement");
@@ -3217,6 +3360,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
// Construct: { vresult = exp; return cases.dim + 1; }
exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp);
exp->op = TOKconstruct;
exp = exp->semantic(sc);
Statement *s1 = new ExpStatement(loc, exp);
Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
@@ -3233,6 +3377,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
VarExp *v = new VarExp(0, fd->vresult);
exp = new AssignExp(loc, v, exp);
exp->op = TOKconstruct;
exp = exp->semantic(sc);
}
@@ -3757,9 +3902,10 @@ Statement *TryCatchStatement::semantic(Scope *sc)
}
}
if (!body)
if (!body || body->isEmpty())
{
return NULL;
}
return this;
}

View File

@@ -128,6 +128,7 @@ struct Statement : Object
virtual int usesEH();
virtual int blockExit();
virtual int comeFrom();
virtual int isEmpty();
virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
virtual Statements *flatten(Scope *sc);
virtual Expression *interpret(InterState *istate);
@@ -146,9 +147,10 @@ struct Statement : Object
virtual IfStatement *isIfStatement() { return NULL; }
virtual CaseStatement* isCaseStatement() { return NULL; }
// LDC
#if IN_LLVM
virtual void toNakedIR(IRState *irs);
virtual AsmBlockStatement* endsWithAsm();
#endif
};
struct ExpStatement : Statement
@@ -168,8 +170,9 @@ struct ExpStatement : Statement
void toIR(IRState *irs);
// LDC
#if IN_LLVM
void toNakedIR(IRState *irs);
#endif
};
struct CompileStatement : Statement
@@ -209,6 +212,7 @@ struct CompoundStatement : Statement
int usesEH();
int blockExit();
int comeFrom();
int isEmpty();
virtual Statements *flatten(Scope *sc);
ReturnStatement *isReturnStatement();
Expression *interpret(InterState *istate);
@@ -219,9 +223,10 @@ struct CompoundStatement : Statement
virtual void toIR(IRState *irs);
// LDC
#if IN_LLVM
virtual void toNakedIR(IRState *irs);
virtual AsmBlockStatement* endsWithAsm();
#endif
virtual CompoundStatement *isCompoundStatement() { return this; }
};
@@ -272,6 +277,7 @@ struct ScopeStatement : Statement
int usesEH();
int blockExit();
int comeFrom();
int isEmpty();
Expression *interpret(InterState *istate);
Statement *inlineScan(InlineScanState *iss);
@@ -479,6 +485,7 @@ struct SwitchStatement : Statement
{
Expression *condition;
Statement *body;
bool isFinal;
DefaultStatement *sdefault;
@@ -487,10 +494,11 @@ struct SwitchStatement : Statement
int hasNoDefault; // !=0 if no default statement
int hasVars; // !=0 if has variable case values
// LDC
#if IN_LLVM
Statement *enclosingScopeExit;
#endif
SwitchStatement(Loc loc, Expression *c, Statement *b);
SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
@@ -508,11 +516,13 @@ struct CaseStatement : Statement
{
Expression *exp;
Statement *statement;
int index; // which case it is (since we sort this)
block *cblock; // back end: label for the block
// LDC
#if IN_LLVM
Statement *enclosingScopeExit;
#endif
CaseStatement(Loc loc, Expression *exp, Statement *s);
Statement *syntaxCopy();
@@ -530,11 +540,28 @@ struct CaseStatement : Statement
CaseStatement* isCaseStatement() { return this; }
// LDC
#if IN_LLVM
llvm::BasicBlock* bodyBB;
llvm::ConstantInt* llvmIdx;
#endif
};
#if DMDV2
struct CaseRangeStatement : Statement
{
Expression *first;
Expression *last;
Statement *statement;
CaseRangeStatement(Loc loc, Expression *first, Expression *last, Statement *s);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
struct DefaultStatement : Statement
{
Statement *statement;
@@ -542,8 +569,9 @@ struct DefaultStatement : Statement
block *cblock; // back end: label for the block
#endif
// LDC
#if IN_LLVM
Statement *enclosingScopeExit;
#endif
DefaultStatement(Loc loc, Statement *s);
Statement *syntaxCopy();
@@ -558,8 +586,9 @@ struct DefaultStatement : Statement
void toIR(IRState *irs);
// LDC
#if IN_LLVM
llvm::BasicBlock* bodyBB;
#endif
};
struct GotoDefaultStatement : Statement
@@ -634,8 +663,10 @@ struct BreakStatement : Statement
void toIR(IRState *irs);
#if IN_LLVM
// LDC: only set if ident is set: label statement to jump to
LabelStatement *target;
#endif
};
struct ContinueStatement : Statement
@@ -651,8 +682,10 @@ struct ContinueStatement : Statement
void toIR(IRState *irs);
#if IN_LLVM
// LDC: only set if ident is set: label statement to jump to
LabelStatement *target;
#endif
};
struct SynchronizedStatement : Statement
@@ -675,7 +708,9 @@ struct SynchronizedStatement : Statement
elem *esync;
SynchronizedStatement(Loc loc, elem *esync, Statement *body);
void toIR(IRState *irs);
#if IN_LLVM
llvm::Value* llsync;
#endif
};
struct WithStatement : Statement
@@ -837,9 +872,10 @@ struct LabelStatement : Statement
void toIR(IRState *irs);
// LDC
#if IN_LLVM
bool asmLabel; // for labels inside inline assembler
void toNakedIR(IRState *irs);
#endif
};
struct LabelDsymbol : Dsymbol
@@ -873,11 +909,12 @@ struct AsmStatement : Statement
void toIR(IRState *irs);
// LDC
#if IN_LLVM
// non-zero if this is a branch, contains the target labels identifier
Identifier* isBranchToLabel;
void toNakedIR(IRState *irs);
#endif
};
struct AsmBlockStatement : CompoundStatement

View File

@@ -46,7 +46,6 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
stag = NULL;
sinit = NULL;
#endif
scope = NULL;
isnested = 0;
vthis = NULL;
@@ -70,7 +69,7 @@ enum PROT AggregateDeclaration::prot()
void AggregateDeclaration::semantic2(Scope *sc)
{
//printf("AggregateDeclaration::semantic2(%s)\n", toChars());
if (scope)
if (scope && members)
{ error("has forward references");
return;
}
@@ -89,9 +88,10 @@ void AggregateDeclaration::semantic2(Scope *sc)
void AggregateDeclaration::semantic3(Scope *sc)
{ int i;
// LDC
#if IN_LLVM
if (!global.params.useAvailableExternally)
availableExternally = false;
#endif
//printf("AggregateDeclaration::semantic3(%s)\n", toChars());
if (members)
@@ -288,6 +288,7 @@ void StructDeclaration::semantic(Scope *sc)
}
parent = sc->parent;
type = type->semantic(loc, sc);
#if STRUCTTHISREF
handle = type;
#else

View File

@@ -308,7 +308,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
this->members = decldefs;
this->overnext = NULL;
this->overroot = NULL;
this->scope = NULL;
this->semanticRun = 0;
this->onemember = NULL;
this->literal = 0;
}
@@ -337,7 +337,6 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
td = new TemplateDeclaration(loc, ident, p, e, d);
#if IN_LLVM
// LDC
td->intrinsicName = intrinsicName;
#endif
@@ -349,8 +348,9 @@ void TemplateDeclaration::semantic(Scope *sc)
#if LOG
printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars());
#endif
if (scope)
if (semanticRun)
return; // semantic() already run
semanticRun = 1;
if (sc->func)
{
@@ -878,8 +878,8 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
fvarargs = fctor->varargs;
}
nfparams = Argument::dim(fparameters); // number of function parameters
nfargs = fargs->dim; // number of function arguments
nfparams = Argument::dim(fparameters); // number of function parameters
nfargs = fargs ? fargs->dim : 0; // number of function arguments
/* Check for match of function arguments with variadic template
* parameter, such as:
@@ -1329,7 +1329,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
for (TemplateDeclaration *td = this; td; td = td->overnext)
{
if (!td->scope)
if (!td->semanticRun)
{
error("forward reference to template %s", td->toChars());
goto Lerror;
@@ -3215,7 +3215,7 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
this->tinst = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semanticdone = 0;
this->semanticRun = 0;
this->semantictiargsdone = 0;
this->withsym = NULL;
this->nest = 0;
@@ -3249,7 +3249,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
this->tinst = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semanticdone = 0;
this->semanticRun = 0;
this->semantictiargsdone = 1;
this->withsym = NULL;
this->nest = 0;
@@ -3324,13 +3324,13 @@ void TemplateInstance::semantic(Scope *sc)
// get the enclosing template instance from the scope tinst
tinst = sc->tinst;
if (semanticdone != 0)
if (semanticRun != 0)
{
error(loc, "recursive template expansion");
// inst = this;
return;
}
semanticdone = 1;
semanticRun = 1;
#if IN_LLVM
// get the enclosing template instance from the scope tinst
tinst = sc->tinst;
@@ -3474,7 +3474,7 @@ void TemplateInstance::semantic(Scope *sc)
{ Module *m = sc->module->importedFrom;
//printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
a = m->members;
if (m->semanticdone >= 3)
if (m->semanticRun >= 3)
dosemantic3 = 1;
}
for (int i = 0; 1; i++)
@@ -3495,9 +3495,9 @@ void TemplateInstance::semantic(Scope *sc)
// Create our own scope for the template parameters
Scope *scope = tempdecl->scope;
if (!scope)
if (!tempdecl->semanticRun)
{
error("forward reference to template declaration %s\n", tempdecl->toChars());
error("template instantiation %s forward references template declaration %s\n", toChars(), tempdecl->toChars());
return;
}
@@ -3717,6 +3717,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
}
else if (ta)
{
Ltype:
if (ta->ty == Ttuple)
{ // Expand tuple
TypeTuple *tt = (TypeTuple *)ta;
@@ -3752,12 +3753,26 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
ea = ea->optimize(WANTvalue | WANTinterpret);
tiargs->data[j] = ea;
if (ea->op == TOKtype)
tiargs->data[j] = ea->type;
{ ta = ea->type;
goto Ltype;
}
if (ea->op == TOKtuple)
{ // Expand tuple
TupleExp *te = (TupleExp *)ea;
size_t dim = te->exps->dim;
tiargs->remove(j);
if (dim)
{ tiargs->reserve(dim);
for (size_t i = 0; i < dim; i++)
tiargs->insert(j + i, te->exps->data[i]);
}
j--;
}
}
else if (sa)
{
TemplateDeclaration *td = sa->isTemplateDeclaration();
if (td && !td->scope && td->literal)
if (td && !td->semanticRun && td->literal)
td->semantic(sc);
}
else
@@ -3898,6 +3913,23 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
#if LOG
printf("TemplateInstance::findBestMatch()\n");
#endif
// First look for forward references
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
{
if (!td->semanticRun)
{
if (td->scope)
{ // Try to fix forward reference
td->semantic(td->scope);
}
if (!td->semanticRun)
{
error("%s forward references template declaration %s\n", toChars(), td->toChars());
return NULL;
}
}
}
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
{
MATCH m;
@@ -3914,11 +3946,7 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
dedtypes.setDim(td->parameters->dim);
dedtypes.zero();
if (!td->scope)
{
error("forward reference to template declaration %s", td->toChars());
return NULL;
}
assert(td->semanticRun);
m = td->matchWithInstance(this, &dedtypes, 0);
//printf("matchWithInstance = %d\n", m);
if (!m) // no match at all
@@ -4212,7 +4240,7 @@ Identifier *TemplateInstance::genIdent()
* template instance arguments.
*/
void TemplateInstance::declareParameters(Scope *scope)
void TemplateInstance::declareParameters(Scope *sc)
{
//printf("TemplateInstance::declareParameters()\n");
for (int i = 0; i < tdtypes.dim; i++)
@@ -4222,7 +4250,7 @@ void TemplateInstance::declareParameters(Scope *scope)
Object *o = (Object *)tdtypes.data[i]; // initializer for tp
//printf("\ttdtypes[%d] = %p\n", i, o);
tempdecl->declareParameter(scope, tp, o);
tempdecl->declareParameter(sc, tp, o);
}
}
@@ -4230,9 +4258,9 @@ void TemplateInstance::declareParameters(Scope *scope)
void TemplateInstance::semantic2(Scope *sc)
{ int i;
if (semanticdone >= 2)
if (semanticRun >= 2)
return;
semanticdone = 2;
semanticRun = 2;
#if LOG
printf("+TemplateInstance::semantic2('%s')\n", toChars());
#endif
@@ -4262,12 +4290,12 @@ printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
void TemplateInstance::semantic3(Scope *sc)
{
#if LOG
printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone);
printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
#endif
//if (toChars()[0] == 'D') *(char*)0=0;
if (semanticdone >= 3)
if (semanticRun >= 3)
return;
semanticdone = 3;
semanticRun = 3;
if (!errors && members)
{
sc = tempdecl->scope;
@@ -4457,7 +4485,6 @@ TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual,
this->tqual = tqual;
this->idents = idents;
this->tiargs = tiargs ? tiargs : new Objects();
this->scope = NULL;
}
Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
@@ -4491,7 +4518,7 @@ void TemplateMixin::semantic(Scope *sc)
printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
fflush(stdout);
#endif
if (semanticdone &&
if (semanticRun &&
// This for when a class/struct contains mixin members, and
// is done over because of forward references
(!parent || !toParent()->isAggregateDeclaration()))
@@ -4501,8 +4528,8 @@ void TemplateMixin::semantic(Scope *sc)
#endif
return;
}
if (!semanticdone)
semanticdone = 1;
if (!semanticRun)
semanticRun = 1;
#if LOG
printf("\tdo semantic\n");
#endif
@@ -4577,7 +4604,7 @@ void TemplateMixin::semantic(Scope *sc)
assert(tempdecl);
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
{
if (!td->scope)
if (!td->semanticRun)
{
/* Cannot handle forward references if mixin is a struct member,
* because addField must happen during struct's semantic, not
@@ -4585,7 +4612,7 @@ void TemplateMixin::semantic(Scope *sc)
* runDeferred will re-run mixin's semantic outside of the struct's
* semantic.
*/
semanticdone = 0;
semanticRun = 0;
AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
if (ad)
ad->sizeok = 2;
@@ -4691,19 +4718,19 @@ void TemplateMixin::semantic(Scope *sc)
argsym = new ScopeDsymbol();
argsym->parent = scy->parent;
Scope *scope = scy->push(argsym);
Scope *argscope = scy->push(argsym);
unsigned errorsave = global.errors;
// Declare each template parameter as an alias for the argument type
declareParameters(scope);
declareParameters(argscope);
// Add members to enclosing scope, as well as this scope
for (unsigned i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
s->addMember(scope, this, i);
s->addMember(argscope, this, i);
//sc->insert(s);
//printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
//printf("s->parent = %s\n", s->parent->toChars());
@@ -4714,7 +4741,7 @@ void TemplateMixin::semantic(Scope *sc)
printf("\tdo semantic() on template instance members '%s'\n", toChars());
#endif
Scope *sc2;
sc2 = scope->push(this);
sc2 = argscope->push(this);
sc2->offset = sc->offset;
static int nest;
@@ -4757,7 +4784,7 @@ void TemplateMixin::semantic(Scope *sc)
sc2->pop();
scope->pop();
argscope->pop();
// if (!isAnonymous())
{
@@ -4771,9 +4798,9 @@ void TemplateMixin::semantic(Scope *sc)
void TemplateMixin::semantic2(Scope *sc)
{ int i;
if (semanticdone >= 2)
if (semanticRun >= 2)
return;
semanticdone = 2;
semanticRun = 2;
#if LOG
printf("+TemplateMixin::semantic2('%s')\n", toChars());
#endif
@@ -4801,9 +4828,9 @@ void TemplateMixin::semantic2(Scope *sc)
void TemplateMixin::semantic3(Scope *sc)
{ int i;
if (semanticdone >= 3)
if (semanticRun >= 3)
return;
semanticdone = 3;
semanticRun = 3;
#if LOG
printf("TemplateMixin::semantic3('%s')\n", toChars());
#endif

View File

@@ -61,7 +61,8 @@ struct TemplateDeclaration : ScopeDsymbol
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
TemplateDeclaration *overroot; // first in overnext list
Scope *scope;
int semanticRun; // 1 semantic() run
Dsymbol *onemember; // if !=NULL then one member of this template
int literal; // this template declaration is a literal
@@ -284,7 +285,7 @@ struct TemplateInstance : ScopeDsymbol
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
// sole member
WithScopeSymbol *withsym; // if a member of a with statement
int semanticdone; // has semantic() been done?
int semanticRun; // has semantic() been done?
int semantictiargsdone; // has semanticTiargs() been done?
int nest; // for recursion detection
int havetempdecl; // 1 if used second constructor
@@ -343,8 +344,6 @@ struct TemplateMixin : TemplateInstance
Array *idents;
Type *tqual;
Scope *scope; // for forward referencing
TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);