mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Merged dmdfe 2.031.
This commit is contained in:
@@ -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;
|
||||
|
||||
143
dmd2/attrib.c
143
dmd2/attrib.c
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
346
dmd2/cast.c
346
dmd2/cast.c
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
46
dmd2/class.c
46
dmd2/class.c
@@ -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;
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 **********************/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -33,7 +33,6 @@ EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
|
||||
#if IN_DMD
|
||||
sinit = NULL;
|
||||
#endif
|
||||
scope = NULL;
|
||||
isdeprecated = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
55
dmd2/func.c
55
dmd2/func.c
@@ -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 ****************************/
|
||||
|
||||
|
||||
157
dmd2/import.c
157
dmd2/import.c
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
71
dmd2/init.c
71
dmd2/init.c
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -113,9 +113,9 @@ char *Declaration::mangle()
|
||||
case LINKd:
|
||||
break;
|
||||
|
||||
// LDC
|
||||
#if IN_LLVM
|
||||
case LINKintrinsic:
|
||||
|
||||
#endif
|
||||
case LINKc:
|
||||
case LINKwindows:
|
||||
case LINKpascal:
|
||||
|
||||
@@ -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;
|
||||
|
||||
10
dmd2/mars.h
10
dmd2/mars.h
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
146
dmd2/mtype.c
146
dmd2/mtype.c
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
82
dmd2/parse.c
82
dmd2/parse.c
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
172
dmd2/statement.c
172
dmd2/statement.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
111
dmd2/template.c
111
dmd2/template.c
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user