mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Merge SiegeLord's dmdfe 1.064 patch.
This commit is contained in:
@@ -220,6 +220,7 @@ struct BaseClass
|
||||
#define CLASSINFO_SIZE (0x3C+16+4) // value of ClassInfo.size
|
||||
#else
|
||||
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
|
||||
#define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size
|
||||
#endif
|
||||
|
||||
struct ClassDeclaration : AggregateDeclaration
|
||||
@@ -267,6 +268,7 @@ struct ClassDeclaration : AggregateDeclaration
|
||||
#define OFFSET_RUNTIME 0x76543210
|
||||
virtual int isBaseOf(ClassDeclaration *cd, int *poffset);
|
||||
|
||||
virtual int isBaseInfoComplete();
|
||||
Dsymbol *search(Loc, Identifier *ident, int flags);
|
||||
#if DMDV2
|
||||
int isFuncHidden(FuncDeclaration *fd);
|
||||
@@ -322,6 +324,7 @@ struct InterfaceDeclaration : ClassDeclaration
|
||||
int isBaseOf(ClassDeclaration *cd, int *poffset);
|
||||
int isBaseOf(BaseClass *bc, int *poffset);
|
||||
const char *kind();
|
||||
int isBaseInfoComplete();
|
||||
int vtblOffset();
|
||||
#if DMDV2
|
||||
int isCPPinterface();
|
||||
|
||||
23
dmd/attrib.c
23
dmd/attrib.c
@@ -341,17 +341,24 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (decl)
|
||||
{
|
||||
buf->writenl();
|
||||
buf->writeByte('{');
|
||||
buf->writenl();
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
if (decl->dim == 0)
|
||||
buf->writestring("{}");
|
||||
else if (decl->dim == 1)
|
||||
((Dsymbol *)decl->data[0])->toCBuffer(buf, hgs);
|
||||
else
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)decl->data[i];
|
||||
buf->writenl();
|
||||
buf->writeByte('{');
|
||||
buf->writenl();
|
||||
for (unsigned i = 0; i < decl->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (Dsymbol *)decl->data[i];
|
||||
|
||||
buf->writestring(" ");
|
||||
s->toCBuffer(buf, hgs);
|
||||
buf->writestring(" ");
|
||||
s->toCBuffer(buf, hgs);
|
||||
}
|
||||
buf->writeByte('}');
|
||||
}
|
||||
buf->writeByte('}');
|
||||
}
|
||||
else
|
||||
buf->writeByte(';');
|
||||
|
||||
35
dmd/class.c
35
dmd/class.c
@@ -556,7 +556,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
|
||||
if (storage_class & STCauto)
|
||||
error("storage class has no effect: auto");
|
||||
error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
|
||||
if (storage_class & STCscope)
|
||||
isscope = 1;
|
||||
if (storage_class & STCabstract)
|
||||
@@ -823,6 +823,23 @@ int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* Determine if 'this' has complete base class information.
|
||||
* This is used to detect forward references in covariant overloads.
|
||||
*/
|
||||
|
||||
int ClassDeclaration::isBaseInfoComplete()
|
||||
{
|
||||
if (!baseClass)
|
||||
return ident == Id::Object;
|
||||
for (int i = 0; i < baseclasses->dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)baseclasses->data[i];
|
||||
if (!b->base || !b->base->isBaseInfoComplete())
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
Dsymbol *s;
|
||||
@@ -1314,6 +1331,22 @@ int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* Determine if 'this' has clomplete base class information.
|
||||
* This is used to detect forward references in covariant overloads.
|
||||
*/
|
||||
|
||||
int InterfaceDeclaration::isBaseInfoComplete()
|
||||
{
|
||||
assert(!baseClass);
|
||||
for (int i = 0; i < baseclasses->dim; i++)
|
||||
{ BaseClass *b = (BaseClass *)baseclasses->data[i];
|
||||
if (!b->base || !b->base->isBaseInfoComplete ())
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* Determine if slot 0 of the vtbl[] is reserved for something else.
|
||||
* For class objects, yes, this is where the ClassInfo ptr goes.
|
||||
|
||||
@@ -562,13 +562,11 @@ Expression *Shl(Type *type, Expression *e1, Expression *e2)
|
||||
}
|
||||
|
||||
Expression *Shr(Type *type, Expression *e1, Expression *e2)
|
||||
{ Expression *e;
|
||||
{
|
||||
Loc loc = e1->loc;
|
||||
unsigned count;
|
||||
dinteger_t value;
|
||||
|
||||
value = e1->toInteger();
|
||||
count = e2->toInteger();
|
||||
dinteger_t value = e1->toInteger();
|
||||
unsigned count = e2->toInteger();
|
||||
switch (e1->type->toBasetype()->ty)
|
||||
{
|
||||
case Tint8:
|
||||
@@ -603,21 +601,22 @@ Expression *Shr(Type *type, Expression *e1, Expression *e2)
|
||||
value = (d_uns64)(value) >> count;
|
||||
break;
|
||||
|
||||
case Terror:
|
||||
return e1;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
e = new IntegerExp(loc, value, type);
|
||||
Expression *e = new IntegerExp(loc, value, type);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *Ushr(Type *type, Expression *e1, Expression *e2)
|
||||
{ Expression *e;
|
||||
{
|
||||
Loc loc = e1->loc;
|
||||
unsigned count;
|
||||
dinteger_t value;
|
||||
|
||||
value = e1->toInteger();
|
||||
count = e2->toInteger();
|
||||
dinteger_t value = e1->toInteger();
|
||||
unsigned count = e2->toInteger();
|
||||
switch (e1->type->toBasetype()->ty)
|
||||
{
|
||||
case Tint8:
|
||||
@@ -642,10 +641,13 @@ Expression *Ushr(Type *type, Expression *e1, Expression *e2)
|
||||
value = (d_uns64)(value) >> count;
|
||||
break;
|
||||
|
||||
case Terror:
|
||||
return e1;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
e = new IntegerExp(loc, value, type);
|
||||
Expression *e = new IntegerExp(loc, value, type);
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -1050,7 +1052,7 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
|
||||
Loc loc = e1->loc;
|
||||
|
||||
//printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars());
|
||||
//printf("e1->type = %s\n", e1->type->toChars());
|
||||
//printf("\te1->type = %s\n", e1->type->toChars());
|
||||
if (type->equals(e1->type) && to->equals(type))
|
||||
return e1;
|
||||
|
||||
@@ -1069,14 +1071,10 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
|
||||
}
|
||||
|
||||
if (e1->op == TOKarrayliteral && typeb == tb)
|
||||
{
|
||||
return e1;
|
||||
}
|
||||
|
||||
if (e1->isConst() != 1)
|
||||
{
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
|
||||
if (tb->ty == Tbool)
|
||||
e = new IntegerExp(loc, e1->toInteger() != 0, type);
|
||||
@@ -1086,7 +1084,7 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
|
||||
{ dinteger_t result;
|
||||
real_t r = e1->toReal();
|
||||
|
||||
switch (type->toBasetype()->ty)
|
||||
switch (typeb->ty)
|
||||
{
|
||||
case Tint8: result = (d_int8)r; break;
|
||||
case Tchar:
|
||||
@@ -1327,7 +1325,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
Type *t2 = e2->type->toBasetype();
|
||||
|
||||
//printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
|
||||
//printf("\tt1 = %s, t2 = %s\n", t1->toChars(), t2->toChars());
|
||||
//printf("\tt1 = %s, t2 = %s, type = %s\n", t1->toChars(), t2->toChars(), type->toChars());
|
||||
|
||||
if (e1->op == TOKnull && (e2->op == TOKint64 || e2->op == TOKstructliteral))
|
||||
{ e = e2;
|
||||
@@ -1465,7 +1463,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
|
||||
if (type->toBasetype()->ty == Tsarray)
|
||||
{
|
||||
e->type = new TypeSArray(e1->type->toBasetype()->next, new IntegerExp(0, es1->elements->dim, Type::tindex));
|
||||
e->type = new TypeSArray(t1->next, new IntegerExp(loc, es1->elements->dim, Type::tindex));
|
||||
e->type = e->type->semantic(loc, NULL);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -678,7 +678,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
|
||||
#endif
|
||||
this->loc = loc;
|
||||
offset = 0;
|
||||
noauto = 0;
|
||||
noscope = 0;
|
||||
#if DMDV2
|
||||
isargptr = FALSE;
|
||||
#endif
|
||||
@@ -821,7 +821,7 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
}
|
||||
if ((storage_class & STCauto) && !inferred)
|
||||
error("both auto and explicit type given");
|
||||
error("storage class 'auto' has no effect if type is not inferred, did you mean 'scope'?");
|
||||
|
||||
if (tb->ty == Ttuple)
|
||||
{ /* Instead, declare variables for each of the tuple elements
|
||||
@@ -959,7 +959,7 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (type->isscope() && !noauto)
|
||||
if (type->isscope() && !noscope)
|
||||
{
|
||||
if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd)
|
||||
{
|
||||
@@ -1431,7 +1431,7 @@ Expression *VarDeclaration::callScopeDtor(Scope *sc)
|
||||
{ Expression *e = NULL;
|
||||
|
||||
//printf("VarDeclaration::callScopeDtor() %s\n", toChars());
|
||||
if (storage_class & STCscope && !noauto)
|
||||
if (storage_class & STCscope && !noscope)
|
||||
{
|
||||
for (ClassDeclaration *cd = type->isClassHandle();
|
||||
cd;
|
||||
@@ -1641,7 +1641,7 @@ TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo)
|
||||
ThisDeclaration::ThisDeclaration(Loc loc, Type *t)
|
||||
: VarDeclaration(loc, t, Id::This, NULL)
|
||||
{
|
||||
noauto = 1;
|
||||
noscope = 1;
|
||||
}
|
||||
|
||||
Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s)
|
||||
|
||||
@@ -273,7 +273,7 @@ struct VarDeclaration : Declaration
|
||||
{
|
||||
Initializer *init;
|
||||
unsigned offset;
|
||||
int noauto; // no scope semantics
|
||||
int noscope; // no scope semantics
|
||||
#if DMDV2
|
||||
FuncDeclarations nestedrefs; // referenced by these lexically nested functions
|
||||
bool isargptr; // if parameter that _argptr points to
|
||||
|
||||
80
dmd/doc.c
80
dmd/doc.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -358,6 +358,78 @@ void Module::gendocfile()
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* Having unmatched parentheses can hose the output of Ddoc,
|
||||
* as the macros depend on properly nested parentheses.
|
||||
* Fix by replacing unmatched ( with $(LPAREN) and unmatched ) with $(RPAREN).
|
||||
*/
|
||||
void escapeStrayParenthesis(OutBuffer *buf, unsigned start, Loc loc)
|
||||
{
|
||||
unsigned par_open = 0;
|
||||
|
||||
for (unsigned u = start; u < buf->offset; u++)
|
||||
{
|
||||
unsigned char c = buf->data[u];
|
||||
switch(c)
|
||||
{
|
||||
case '(':
|
||||
par_open++;
|
||||
break;
|
||||
|
||||
case ')':
|
||||
if (par_open == 0)
|
||||
{
|
||||
//stray ')'
|
||||
if (global.params.warnings)
|
||||
warning(loc, "Ddoc: Stray ')'. This may cause incorrect Ddoc output."
|
||||
" Use $(RPAREN) instead for unpaired right parentheses.");
|
||||
buf->remove(u, 1); //remove the )
|
||||
buf->insert(u, "$(RPAREN)", 9); //insert this instead
|
||||
u += 8; //skip over newly inserted macro
|
||||
}
|
||||
else
|
||||
par_open--;
|
||||
break;
|
||||
#if 0
|
||||
// For this to work, loc must be set to the beginning of the passed
|
||||
// text which is currently not possible
|
||||
// (loc is set to the Loc of the Dsymbol)
|
||||
case '\n':
|
||||
loc.linnum++;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (par_open) // if any unmatched lparens
|
||||
{ par_open = 0;
|
||||
for (unsigned u = buf->offset; u > start;)
|
||||
{ u--;
|
||||
unsigned char c = buf->data[u];
|
||||
switch(c)
|
||||
{
|
||||
case ')':
|
||||
par_open++;
|
||||
break;
|
||||
|
||||
case '(':
|
||||
if (par_open == 0)
|
||||
{
|
||||
//stray '('
|
||||
if (global.params.warnings)
|
||||
warning(loc, "Ddoc: Stray '('. This may cause incorrect Ddoc output."
|
||||
" Use $(LPAREN) instead for unpaired left parentheses.");
|
||||
buf->remove(u, 1); //remove the (
|
||||
buf->insert(u, "$(LPAREN)", 9); //insert this instead
|
||||
}
|
||||
else
|
||||
par_open--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************* emitComment **********************************/
|
||||
|
||||
/*
|
||||
@@ -1082,6 +1154,7 @@ void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
buf->writestring("$(DDOC_SUMMARY ");
|
||||
unsigned o = buf->offset;
|
||||
buf->write(sec->body, sec->bodylen);
|
||||
escapeStrayParenthesis(buf, o, s->loc);
|
||||
highlightText(sc, s, buf, o);
|
||||
buf->writestring(")\n");
|
||||
}
|
||||
@@ -1119,10 +1192,12 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
buf->writestring("$(DDOC_SECTION ");
|
||||
// Replace _ characters with spaces
|
||||
buf->writestring("$(DDOC_SECTION_H ");
|
||||
unsigned o = buf->offset;
|
||||
for (unsigned u = 0; u < namelen; u++)
|
||||
{ unsigned char c = name[u];
|
||||
buf->writeByte((c == '_') ? ' ' : c);
|
||||
}
|
||||
escapeStrayParenthesis(buf, o, s->loc);
|
||||
buf->writestring(":)\n");
|
||||
}
|
||||
else
|
||||
@@ -1132,6 +1207,7 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
L1:
|
||||
unsigned o = buf->offset;
|
||||
buf->write(body, bodylen);
|
||||
escapeStrayParenthesis(buf, o, s->loc);
|
||||
highlightText(sc, s, buf, o);
|
||||
buf->writestring(")\n");
|
||||
}
|
||||
@@ -1213,12 +1289,14 @@ void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
arg->type->toCBuffer(buf, arg->ident, &hgs);
|
||||
else
|
||||
buf->write(namestart, namelen);
|
||||
escapeStrayParenthesis(buf, o, s->loc);
|
||||
highlightCode(sc, s, buf, o);
|
||||
buf->writestring(")\n");
|
||||
|
||||
buf->writestring("$(DDOC_PARAM_DESC ");
|
||||
o = buf->offset;
|
||||
buf->write(textstart, textlen);
|
||||
escapeStrayParenthesis(buf, o, s->loc);
|
||||
highlightText(sc, s, buf, o);
|
||||
buf->writestring(")");
|
||||
buf->writestring(")\n");
|
||||
|
||||
@@ -782,6 +782,13 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
||||
|
||||
void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (precedence[e->op] == PREC_zero)
|
||||
printf("precedence not defined for token '%s'\n",Token::tochars[e->op]);
|
||||
#endif
|
||||
assert(precedence[e->op] != PREC_zero);
|
||||
assert(pr != PREC_zero);
|
||||
|
||||
//if (precedence[e->op] == 0) e->dump(0);
|
||||
if (precedence[e->op] < pr ||
|
||||
/* Despite precedence, we don't allow a<b<c expressions.
|
||||
@@ -3991,7 +3998,7 @@ Expression *VarExp::semantic(Scope *sc)
|
||||
if (v->isSameAsInitializer() && type->toBasetype()->ty != Tsarray && v->init)
|
||||
{
|
||||
ExpInitializer *ei = v->init->isExpInitializer();
|
||||
if (ei)
|
||||
if (ei && ei->exp->type)
|
||||
{
|
||||
//ei->exp->implicitCastTo(sc, type)->print();
|
||||
return ei->exp->implicitCastTo(sc, type);
|
||||
@@ -4036,7 +4043,7 @@ void VarExp::checkEscape()
|
||||
// if reference type
|
||||
if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass)
|
||||
{
|
||||
if (v->isScope() && !v->noauto)
|
||||
if (v->isScope() && !v->noscope)
|
||||
error("escaping reference to auto local %s", v->toChars());
|
||||
else if (v->storage_class & STCvariadic)
|
||||
error("escaping reference to variadic parameter %s", v->toChars());
|
||||
@@ -6843,9 +6850,16 @@ Expression *CallExp::modifiableLvalue(Scope *sc, Expression *e)
|
||||
}
|
||||
|
||||
void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{ int i;
|
||||
|
||||
expToCBuffer(buf, hgs, e1, precedence[op]);
|
||||
{
|
||||
if (e1->op == TOKtype)
|
||||
/* Avoid parens around type to prevent forbidden cast syntax:
|
||||
* (sometype)(arg1)
|
||||
* This is ok since types in constructor calls
|
||||
* can never depend on parens anyway
|
||||
*/
|
||||
e1->toCBuffer(buf, hgs);
|
||||
else
|
||||
expToCBuffer(buf, hgs, e1, precedence[op]);
|
||||
buf->writeByte('(');
|
||||
argsToCBuffer(buf, arguments, hgs);
|
||||
buf->writeByte(')');
|
||||
@@ -7784,6 +7798,12 @@ Expression *DotExp::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
void DotExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
expToCBuffer(buf, hgs, e1, PREC_primary);
|
||||
buf->writeByte('.');
|
||||
expToCBuffer(buf, hgs, e2, PREC_primary);
|
||||
}
|
||||
|
||||
/************************* CommaExp ***********************************/
|
||||
|
||||
|
||||
@@ -1314,6 +1314,7 @@ struct DotExp : BinExp
|
||||
{
|
||||
DotExp(Loc loc, Expression *e1, Expression *e2);
|
||||
Expression *semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct CommaExp : BinExp
|
||||
|
||||
@@ -1021,7 +1021,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
loc = fensure->loc;
|
||||
|
||||
v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
|
||||
v->noauto = 1;
|
||||
v->noscope = 1;
|
||||
#if DMDV2
|
||||
if (!isVirtual())
|
||||
v->storage_class |= STCconst;
|
||||
@@ -1460,7 +1460,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
if (v->type->toBasetype()->ty == Tsarray)
|
||||
continue;
|
||||
|
||||
Expression *e = v->callAutoDtor(sc);
|
||||
Expression *e = v->callScopeDtor(sc);
|
||||
if (e)
|
||||
{ Statement *s = new ExpStatement(0, e);
|
||||
s = s->semantic(sc);
|
||||
|
||||
@@ -381,8 +381,8 @@ void init()
|
||||
Y(Tint64, Tdchar)
|
||||
Y(Tuns64, Tdchar)
|
||||
|
||||
Y(Tint64, Tuns64)
|
||||
Y(Tuns64, Tint64)
|
||||
// Y(Tint64, Tuns64)
|
||||
// Y(Tuns64, Tint64)
|
||||
|
||||
for (i = 0; i < TMAX; i++)
|
||||
for (j = 0; j < TMAX; j++)
|
||||
|
||||
@@ -740,6 +740,10 @@ Expression *ForStatement::interpret(InterState *istate)
|
||||
|
||||
Expression *ForeachStatement::interpret(InterState *istate)
|
||||
{
|
||||
#if 1
|
||||
assert(0); // rewritten to ForStatement
|
||||
return NULL;
|
||||
#else
|
||||
#if LOG
|
||||
printf("ForeachStatement::interpret()\n");
|
||||
#endif
|
||||
@@ -822,11 +826,16 @@ Expression *ForeachStatement::interpret(InterState *istate)
|
||||
if (key)
|
||||
key->value = keysave;
|
||||
return e;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
Expression *ForeachRangeStatement::interpret(InterState *istate)
|
||||
{
|
||||
#if 1
|
||||
assert(0); // rewritten to ForStatement
|
||||
return NULL;
|
||||
#else
|
||||
#if LOG
|
||||
printf("ForeachRangeStatement::interpret()\n");
|
||||
#endif
|
||||
@@ -907,6 +916,7 @@ Expression *ForeachRangeStatement::interpret(InterState *istate)
|
||||
}
|
||||
key->value = keysave;
|
||||
return e;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ Global::Global()
|
||||
|
||||
copyright = "Copyright (c) 1999-2010 by Digital Mars and Tomas Lindquist Olsen";
|
||||
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
||||
version = "v1.063";
|
||||
version = "v1.064";
|
||||
ldc_version = "LDC trunk";
|
||||
llvm_version = "LLVM 2.8";
|
||||
global.structalign = 8;
|
||||
|
||||
24
dmd/mtype.c
24
dmd/mtype.c
@@ -2846,18 +2846,26 @@ int Type::covariant(Type *t)
|
||||
|
||||
if (t1n->equals(t2n))
|
||||
goto Lcovariant;
|
||||
if (t1n->ty != Tclass || t2n->ty != Tclass)
|
||||
goto Lnotcovariant;
|
||||
|
||||
// If t1n is forward referenced:
|
||||
ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
|
||||
if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration())
|
||||
if (t1n->ty == Tclass && t2n->ty == Tclass)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
|
||||
ClassDeclaration *cd2 = ((TypeClass *)t2n)->sym;
|
||||
if (cd == cd2)
|
||||
goto Lcovariant;
|
||||
|
||||
// If t1n is forward referenced:
|
||||
#if 0
|
||||
if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration())
|
||||
#else
|
||||
if (!cd->isBaseInfoComplete())
|
||||
#endif
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
if (t1n->implicitConvTo(t2n))
|
||||
goto Lcovariant;
|
||||
|
||||
goto Lnotcovariant;
|
||||
}
|
||||
|
||||
|
||||
@@ -532,7 +532,7 @@ struct TypeDelegate : Type
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize(); // added in LDC
|
||||
unsigned alignsize();
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *defaultInit(Loc loc);
|
||||
int isZeroInit(Loc loc);
|
||||
|
||||
17
dmd/parse.c
17
dmd/parse.c
@@ -5469,6 +5469,15 @@ enum PREC precedence[TOKMAX];
|
||||
|
||||
void initPrecedence()
|
||||
{
|
||||
for (int i = 0; i < TOKMAX; i++)
|
||||
precedence[i] = PREC_zero;
|
||||
|
||||
precedence[TOKtype] = PREC_expr;
|
||||
precedence[TOKerror] = PREC_expr;
|
||||
|
||||
precedence[TOKtypeof] = PREC_primary;
|
||||
precedence[TOKmixin] = PREC_primary;
|
||||
|
||||
precedence[TOKdotvar] = PREC_primary;
|
||||
precedence[TOKimport] = PREC_primary;
|
||||
precedence[TOKidentifier] = PREC_primary;
|
||||
@@ -5484,19 +5493,26 @@ void initPrecedence()
|
||||
precedence[TOKassert] = PREC_primary;
|
||||
precedence[TOKfunction] = PREC_primary;
|
||||
precedence[TOKvar] = PREC_primary;
|
||||
precedence[TOKsymoff] = PREC_primary;
|
||||
precedence[TOKstructliteral] = PREC_primary;
|
||||
precedence[TOKarraylength] = PREC_primary;
|
||||
precedence[TOKtuple] = PREC_primary;
|
||||
#if DMDV2
|
||||
precedence[TOKtraits] = PREC_primary;
|
||||
precedence[TOKdefault] = PREC_primary;
|
||||
#endif
|
||||
|
||||
// post
|
||||
precedence[TOKdotti] = PREC_primary;
|
||||
precedence[TOKdot] = PREC_primary;
|
||||
precedence[TOKdottd] = PREC_primary;
|
||||
// precedence[TOKarrow] = PREC_primary;
|
||||
precedence[TOKplusplus] = PREC_primary;
|
||||
precedence[TOKminusminus] = PREC_primary;
|
||||
precedence[TOKcall] = PREC_primary;
|
||||
precedence[TOKslice] = PREC_primary;
|
||||
precedence[TOKarray] = PREC_primary;
|
||||
precedence[TOKindex] = PREC_primary;
|
||||
|
||||
precedence[TOKaddress] = PREC_unary;
|
||||
precedence[TOKstar] = PREC_unary;
|
||||
@@ -5579,6 +5595,7 @@ void initPrecedence()
|
||||
precedence[TOKxorass] = PREC_assign;
|
||||
|
||||
precedence[TOKcomma] = PREC_expr;
|
||||
precedence[TOKdeclaration] = PREC_expr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1719,7 +1719,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
if (!sc->func->vresult && tret && tret != Type::tvoid)
|
||||
{
|
||||
VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
|
||||
v->noauto = 1;
|
||||
v->noscope = 1;
|
||||
v->semantic(sc);
|
||||
if (!sc->insert(v))
|
||||
assert(0);
|
||||
@@ -2311,7 +2311,7 @@ Statement *IfStatement::semantic(Scope *sc)
|
||||
|
||||
Type *t = arg->type ? arg->type : condition->type;
|
||||
match = new VarDeclaration(loc, t, arg->ident, NULL);
|
||||
match->noauto = 1;
|
||||
match->noscope = 1;
|
||||
match->semantic(scd);
|
||||
if (!scd->insert(match))
|
||||
assert(0);
|
||||
@@ -3427,7 +3427,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
||||
if (!fd->vresult)
|
||||
{ // Declare vresult
|
||||
VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
|
||||
v->noauto = 1;
|
||||
v->noscope = 1;
|
||||
v->semantic(scx);
|
||||
if (!scx->insert(v))
|
||||
assert(0);
|
||||
|
||||
134
dmd/template.c
134
dmd/template.c
@@ -975,19 +975,26 @@ L2:
|
||||
#endif
|
||||
|
||||
// Loop through the function parameters
|
||||
for (i = 0; i < nfparams; i++)
|
||||
for (size_t parami = 0; parami < nfparams; parami++)
|
||||
{
|
||||
/* Skip over function parameters which wound up
|
||||
* as part of a template tuple parameter.
|
||||
*/
|
||||
if (i == fptupindex)
|
||||
{ if (fptupindex == nfparams - 1)
|
||||
break;
|
||||
i += tuple_dim - 1;
|
||||
if (parami == fptupindex)
|
||||
continue;
|
||||
}
|
||||
/* Set i = index into function arguments
|
||||
* Function parameters correspond to function arguments as follows.
|
||||
* Note that tuple_dim may be zero, and there may be default or
|
||||
* variadic arguments at the end.
|
||||
* arg [0..fptupindex] == param[0..fptupindex]
|
||||
* arg [fptupindex..fptupindex+tuple_dim] == param[fptupindex]
|
||||
* arg[fputupindex+dim.. ] == param[fptupindex+1.. ]
|
||||
*/
|
||||
i = parami;
|
||||
if (fptupindex >= 0 && parami > fptupindex)
|
||||
i += tuple_dim - 1;
|
||||
|
||||
Parameter *fparam = Parameter::getNth(fparameters, i);
|
||||
Parameter *fparam = Parameter::getNth(fparameters, parami);
|
||||
|
||||
if (i >= nfargs) // if not enough arguments
|
||||
{
|
||||
@@ -2181,6 +2188,63 @@ MATCH TypeTypedef::deduceType(Scope *sc, Type *tparam, TemplateParameters *param
|
||||
return Type::deduceType(sc, tparam, parameters, dedtypes);
|
||||
}
|
||||
|
||||
/* Helper for TypeClass::deduceType().
|
||||
* Classes can match with implicit conversion to a base class or interface.
|
||||
* This is complicated, because there may be more than one base class which
|
||||
* matches. In such cases, one or more parameters remain ambiguous.
|
||||
* For example,
|
||||
*
|
||||
* interface I(X, Y) {}
|
||||
* class C : I(uint, double), I(char, double) {}
|
||||
* C x;
|
||||
* foo(T, U)( I!(T, U) x)
|
||||
*
|
||||
* deduces that U is double, but T remains ambiguous (could be char or uint).
|
||||
*
|
||||
* Given a baseclass b, and initial deduced types 'dedtypes', this function
|
||||
* tries to match tparam with b, and also tries all base interfaces of b.
|
||||
* If a match occurs, numBaseClassMatches is incremented, and the new deduced
|
||||
* types are ANDed with the current 'best' estimate for dedtypes.
|
||||
*/
|
||||
void deduceBaseClassParameters(BaseClass *b,
|
||||
Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes,
|
||||
Objects *best, int &numBaseClassMatches)
|
||||
{
|
||||
TemplateInstance *parti = b->base->parent->isTemplateInstance();
|
||||
if (parti)
|
||||
{
|
||||
// Make a temporary copy of dedtypes so we don't destroy it
|
||||
Objects *tmpdedtypes = new Objects();
|
||||
tmpdedtypes->setDim(dedtypes->dim);
|
||||
memcpy(tmpdedtypes->data, dedtypes->data, dedtypes->dim * sizeof(void *));
|
||||
|
||||
TypeInstance *t = new TypeInstance(0, parti);
|
||||
MATCH m = t->deduceType(sc, tparam, parameters, tmpdedtypes);
|
||||
if (m != MATCHnomatch)
|
||||
{
|
||||
// If this is the first ever match, it becomes our best estimate
|
||||
if (numBaseClassMatches==0)
|
||||
memcpy(best->data, tmpdedtypes->data, tmpdedtypes->dim * sizeof(void *));
|
||||
else for (size_t k = 0; k < tmpdedtypes->dim; ++k)
|
||||
{
|
||||
// If we've found more than one possible type for a parameter,
|
||||
// mark it as unknown.
|
||||
if (tmpdedtypes->data[k] != best->data[k])
|
||||
best->data[k] = dedtypes->data[k];
|
||||
}
|
||||
++numBaseClassMatches;
|
||||
}
|
||||
}
|
||||
// Now recursively test the inherited interfaces
|
||||
for (size_t j = 0; j < b->baseInterfaces_dim; ++j)
|
||||
{
|
||||
deduceBaseClassParameters( &(b->baseInterfaces)[j],
|
||||
sc, tparam, parameters, dedtypes,
|
||||
best, numBaseClassMatches);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
|
||||
{
|
||||
//printf("TypeClass::deduceType(this = %s)\n", toChars());
|
||||
@@ -2196,7 +2260,11 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet
|
||||
if (ti && ti->toAlias() == sym)
|
||||
{
|
||||
TypeInstance *t = new TypeInstance(0, ti);
|
||||
return t->deduceType(sc, tparam, parameters, dedtypes);
|
||||
MATCH m = t->deduceType(sc, tparam, parameters, dedtypes);
|
||||
// Even if the match fails, there is still a chance it could match
|
||||
// a base class.
|
||||
if (m != MATCHnomatch)
|
||||
return m;
|
||||
}
|
||||
|
||||
/* Match things like:
|
||||
@@ -2219,6 +2287,47 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If it matches exactly or via implicit conversion, we're done
|
||||
MATCH m = Type::deduceType(sc, tparam, parameters, dedtypes);
|
||||
if (m != MATCHnomatch)
|
||||
return m;
|
||||
|
||||
/* There is still a chance to match via implicit conversion to
|
||||
* a base class or interface. Because there could be more than one such
|
||||
* match, we need to check them all.
|
||||
*/
|
||||
|
||||
int numBaseClassMatches = 0; // Have we found an interface match?
|
||||
|
||||
// Our best guess at dedtypes
|
||||
Objects *best = new Objects();
|
||||
best->setDim(dedtypes->dim);
|
||||
|
||||
ClassDeclaration *s = sym;
|
||||
while(s && s->baseclasses->dim > 0)
|
||||
{
|
||||
// Test the base class
|
||||
deduceBaseClassParameters((BaseClass *)(s->baseclasses->data[0]),
|
||||
sc, tparam, parameters, dedtypes,
|
||||
best, numBaseClassMatches);
|
||||
|
||||
// Test the interfaces inherited by the base class
|
||||
for (size_t i = 0; i < s->interfaces_dim; ++i)
|
||||
{
|
||||
BaseClass *b = s->interfaces[i];
|
||||
deduceBaseClassParameters(b, sc, tparam, parameters, dedtypes,
|
||||
best, numBaseClassMatches);
|
||||
}
|
||||
s = ((BaseClass *)(s->baseclasses->data[0]))->base;
|
||||
}
|
||||
|
||||
if (numBaseClassMatches == 0)
|
||||
return MATCHnomatch;
|
||||
|
||||
// If we got at least one match, copy the known types into dedtypes
|
||||
memcpy(dedtypes->data, best->data, best->dim * sizeof(void *));
|
||||
return MATCHconvert;
|
||||
}
|
||||
|
||||
// Extra check
|
||||
@@ -2227,7 +2336,7 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet
|
||||
TypeClass *tp = (TypeClass *)tparam;
|
||||
|
||||
//printf("\t%d\n", (MATCH) implicitConvTo(tp));
|
||||
return (MATCH) implicitConvTo(tp);
|
||||
return implicitConvTo(tp);
|
||||
}
|
||||
return Type::deduceType(sc, tparam, parameters, dedtypes);
|
||||
}
|
||||
@@ -3578,8 +3687,11 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
if (global.gag)
|
||||
{ // Try to reset things so we can try again later to instantiate it
|
||||
tempdecl->instances.remove(tempdecl_instance_idx);
|
||||
semanticRun = 0;
|
||||
inst = NULL;
|
||||
if (!(sc->flags & SCOPEstaticif))
|
||||
{ // Bugzilla 4302 for discussion
|
||||
semanticRun = 0;
|
||||
inst = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user