Skip to content

Commit

Permalink
implement const/purity/nothrow/@safe inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Feb 17, 2012
1 parent d448813 commit 5c75bb3
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/expression.c
Expand Up @@ -1547,7 +1547,7 @@ void Expression::checkPurity(Scope *sc, VarDeclaration *v, Expression *ethis)
break;
if (ff->setImpure() && !msg)
{ error("pure function '%s' cannot access mutable static data '%s'",
sc->func->toChars(), v->toChars());
sc->func->toPrettyChars(), v->toChars());
msg = TRUE; // only need the innermost message
}
}
Expand Down
18 changes: 15 additions & 3 deletions src/func.c
Expand Up @@ -1983,6 +1983,8 @@ int FuncDeclaration::overrides(FuncDeclaration *fd)
int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
{
FuncDeclaration *mismatch = NULL;
StorageClass mismatchstc = 0;
int mismatchvi = -1;
int bestvi = -1;
for (int vi = 0; vi < dim; vi++)
{
Expand All @@ -1992,7 +1994,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
if (type->equals(fdv->type)) // if exact match
return vi; // no need to look further

int cov = type->covariant(fdv->type);
StorageClass stc = 0;
int cov = type->covariant(fdv->type, &stc);
//printf("\tbaseclass cov = %d\n", cov);
switch (cov)
{
Expand All @@ -2004,6 +2007,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
break; // keep looking for an exact match

case 2:
mismatchvi = vi;
mismatchstc = stc;
mismatch = fdv; // overrides, but is not covariant
break; // keep looking for an exact match

Expand All @@ -2020,8 +2025,15 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
//type->print();
//mismatch->type->print();
//printf("%s %s\n", type->deco, mismatch->type->deco);
error("of type %s overrides but is not covariant with %s of type %s",
type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars());
//printf("stc = %llx\n", mismatchstc);
if (mismatchstc)
{ // Fix it by modifying the type to add the storage classes
type = type->addStorageClass(mismatchstc);
bestvi = mismatchvi;
}
else
error("of type %s overrides but is not covariant with %s of type %s",
type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars());
}
return bestvi;
}
Expand Down
2 changes: 1 addition & 1 deletion src/mars.c
Expand Up @@ -94,7 +94,7 @@ Global::Global()
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
#endif
;
version = "v2.058";
version = "v2.059";
global.structalign = 8;

memset(&params, 0, sizeof(Param));
Expand Down
65 changes: 52 additions & 13 deletions src/mtype.c
Expand Up @@ -4910,9 +4910,10 @@ Type *TypeFunction::syntaxCopy()
* 2 arguments match as far as overloading goes,
* but types are not covariant
* 3 cannot determine covariance because of forward references
* *pstc STCxxxx which would make it covariant
*/

int Type::covariant(Type *t)
int Type::covariant(Type *t, StorageClass *pstc)
{
#if 0
printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars());
Expand All @@ -4921,6 +4922,10 @@ int Type::covariant(Type *t)
printf("mod = %x, %x\n", mod, t->mod);
#endif

if (pstc)
*pstc = 0;
StorageClass stc = 0;

int inoutmismatch = 0;

TypeFunction *t1;
Expand Down Expand Up @@ -5024,35 +5029,39 @@ int Type::covariant(Type *t)
goto Lnotcovariant;

Lcovariant:
if (t1->isref != t2->isref)
goto Lnotcovariant;

/* Can convert mutable to const
*/
if (!MODimplicitConv(t2->mod, t1->mod))
goto Lnotcovariant;
#if 0
if (t1->mod != t2->mod)
{
if (!(t1->mod & MODconst) && (t2->mod & MODconst))
goto Lnotcovariant;
if (!(t1->mod & MODshared) && (t2->mod & MODshared))
// If adding 'const' will make it covariant
if (MODimplicitConv(t2->mod, MODmerge(t1->mod, MODconst)))
stc |= STCconst;
else
goto Lnotcovariant;
}
#endif

/* Can convert pure to impure, and nothrow to throw
*/
if (!t1->purity && t2->purity)
goto Lnotcovariant;
stc |= STCpure;

if (!t1->isnothrow && t2->isnothrow)
goto Lnotcovariant;

if (t1->isref != t2->isref)
goto Lnotcovariant;
stc |= STCnothrow;

/* Can convert safe/trusted to system
*/
if (t1->trust <= TRUSTsystem && t2->trust >= TRUSTtrusted)
// Should we infer trusted or safe? Go with safe.
stc |= STCsafe;

if (stc)
{ if (pstc)
*pstc = stc;
goto Lnotcovariant;
}

//printf("\tcovaraint: 1\n");
return 1;
Expand Down Expand Up @@ -5908,6 +5917,36 @@ Expression *TypeFunction::defaultInit(Loc loc)
return new ErrorExp();
}

Type *TypeFunction::addStorageClass(StorageClass stc)
{
TypeFunction *t = (TypeFunction *)Type::addStorageClass(stc);
if ((stc & STCpure && !t->purity) ||
(stc & STCnothrow && !t->isnothrow) ||
(stc & STCsafe && t->trust < TRUSTtrusted))
{
// Klunky to change these
TypeFunction *tf = new TypeFunction(t->parameters, t->next, t->varargs, t->linkage, 0);
tf->mod = t->mod;
tf->fargs = fargs;
tf->purity = t->purity;
tf->isnothrow = t->isnothrow;
tf->isproperty = t->isproperty;
tf->isref = t->isref;
tf->trust = t->trust;

if (stc & STCpure)
tf->purity = PUREfwdref;
if (stc & STCnothrow)
tf->isnothrow = true;
if (stc & STCsafe)
tf->trust = TRUSTsafe;

tf->deco = tf->merge()->deco;
t = tf;
}
return t;
}

/***************************** TypeDelegate *****************************/

TypeDelegate::TypeDelegate(Type *t)
Expand Down
5 changes: 3 additions & 2 deletions src/mtype.h
Expand Up @@ -223,7 +223,7 @@ struct Type : Object
virtual Type *syntaxCopy();
int equals(Object *o);
int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType()
int covariant(Type *t);
int covariant(Type *t, StorageClass *pstc = NULL);
char *toChars();
static char needThisPrefix();
static void init();
Expand Down Expand Up @@ -275,7 +275,7 @@ struct Type : Object
Type *addSTC(StorageClass stc);
Type *castMod(unsigned mod);
Type *addMod(unsigned mod);
Type *addStorageClass(StorageClass stc);
virtual Type *addStorageClass(StorageClass stc);
Type *pointerTo();
Type *referenceTo();
Type *arrayOf();
Expand Down Expand Up @@ -633,6 +633,7 @@ struct TypeFunction : TypeNext
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
bool parameterEscapes(Parameter *p);
Type *addStorageClass(StorageClass stc);

int callMatch(Expression *ethis, Expressions *toargs, int flag = 0);
type *toCtype();
Expand Down
19 changes: 19 additions & 0 deletions test/runnable/xtest46.d
Expand Up @@ -4458,6 +4458,25 @@ void test7321()
static assert(is(typeof((){return;})==void function()pure nothrow @safe)); // fail
}

/***************************************************/

class A158
{
pure void foo1() { }
const void foo2() { }
nothrow void foo3() { }
@safe void foo4() { }
}

class B158 : A158
{
override void foo1() { }
override void foo2() { }
override void foo3() { }
override void foo4() { }
}


/***************************************************/

int main()
Expand Down

0 comments on commit 5c75bb3

Please sign in to comment.