Merge SiegeLord's dmdfe 1.064 patch.

This commit is contained in:
Robert Clipsham
2011-01-01 21:23:08 +00:00
parent 5e98bf3c49
commit 65c892ee62
18 changed files with 356 additions and 69 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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