Skip to content

Commit

Permalink
Merge pull request #1722 from 9rnsr/fix9633
Browse files Browse the repository at this point in the history
[REG2.063a] Issue 9633 - compiles trait wrongly returns true even when object method call actually does not compile
  • Loading branch information
WalterBright committed Mar 7, 2013
2 parents ba1009c + 85c896a commit 0679c4c
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 54 deletions.
117 changes: 63 additions & 54 deletions src/expression.c
Expand Up @@ -207,6 +207,61 @@ FuncDeclaration *hasThis(Scope *sc)
return NULL; // don't have 'this' available
}

bool isNeedThisScope(Scope *sc, Declaration *d)
{
if (sc->intypeof == 1)
return false;

AggregateDeclaration *ad = d->isThis();
if (!ad)
return false;
//printf("d = %s, ad = %s\n", d->toChars(), ad->toChars());

for (Dsymbol *s = sc->parent; s; s = s->toParent2())
{
//printf("\ts = %s %s, toParent2() = %p\n", s->kind(), s->toChars(), s->toParent2());
if (AggregateDeclaration *ad2 = s->isAggregateDeclaration())
{
//printf("\t ad2 = %s\n", ad2->toChars());
if (ad2 == ad)
return false;
else if (ad2->isNested())
continue;
else
return true;
}
if (FuncDeclaration *f = s->isFuncDeclaration())
{
if (f->isFuncLiteralDeclaration())
continue;
if (f->isMember2())
break;
if (TemplateDeclaration *td = f->parent->isTemplateDeclaration())
{
if ((td->scope->stc & STCstatic) && td->isMember())
break; // no valid 'this'
}
}
}
return true;
}

Expression *checkRightThis(Scope *sc, Expression *e)
{
if (e->op == TOKvar && e->type->ty != Terror)
{
VarExp *ve = (VarExp *)e;
if (isNeedThisScope(sc, ve->var))
{
//printf("checkRightThis sc->intypeof = %d, ad = %p, func = %p, fdthis = %p\n",
// sc->intypeof, sc->getStructClassScope(), func, fdthis);
e->error("need 'this' for '%s' of type '%s'", ve->var->toChars(), ve->var->type->toChars());
e = new ErrorExp();
}
}
return e;
}


/***************************************
* Pull out any properties.
Expand Down Expand Up @@ -316,55 +371,6 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e)
return e;
}

Expression *checkRightThis(Scope *sc, Expression *e)
{
if (e->op == TOKvar && e->type->ty != Terror)
{
VarExp *ve = (VarExp *)e;

Dsymbol *p = sc->parent;
while (p && p->isTemplateMixin())
p = p->parent;
FuncDeclaration *func = p ? p->isFuncDeclaration() : NULL;
FuncDeclaration *fdthis = hasThis(sc);
#if 1
/* Check special cases inside DeclDefs scope and template constraint
*/
if (func && !fdthis && sc->intypeof == 2)
{
//printf("[%s] func = %s\n", func->loc.toChars(), func->toChars());
for (Dsymbol *s = func->parent; 1; s = s->parent)
{
if (!s)
break;
//printf("\ts = %s %s\n", s->kind(), s->toChars());
if (s->isAggregateDeclaration() || s->isThis())
return e;
FuncDeclaration *f = s->isFuncDeclaration();
if (f)
{
if (f->isMember2())
break;
if (TemplateDeclaration *td = f->parent->isTemplateDeclaration())
{
if ((td->scope->stc & STCstatic) && td->isMember())
break; // no valid 'this'
}
}
}
}
#endif
if (sc->intypeof != 1 && (func && !fdthis || !func && !sc->getStructClassScope()) && ve->var->needThis())
{
//printf("checkRightThis sc->intypeof = %d, ad = %p, func = %p, fdthis = %p\n",
// sc->intypeof, sc->getStructClassScope(), func, fdthis);
e->error("need 'this' for '%s' of type '%s'", ve->var->toChars(), ve->var->type->toChars());
e = new ErrorExp();
}
}
return e;
}

Expression *resolveProperties(Scope *sc, Expression *e)
{
//printf("resolveProperties(%s)\n", e->toChars());
Expand Down Expand Up @@ -8327,7 +8333,7 @@ Expression *CallExp::semantic(Scope *sc)
e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td);
goto Lagain;
}
else if (sc->intypeof != 1 && sc->parent->isFuncDeclaration())
else if (isNeedThisScope(sc, f))
{
error("need 'this' for '%s' of type '%s'", f->toChars(), f->type->toChars());
return new ErrorExp();
Expand Down Expand Up @@ -8398,6 +8404,7 @@ Expression *CallExp::semantic(Scope *sc)
f = resolveFuncCall(loc, sc, f, tiargs, NULL, arguments, 2);
else
{
f = f->toAliasFunc();
TypeFunction *tf = (TypeFunction *)f->type;
if (!tf->callMatch(NULL, arguments))
{
Expand Down Expand Up @@ -8433,7 +8440,7 @@ Expression *CallExp::semantic(Scope *sc)
e1 = new DotVarExp(loc, (new ThisExp(loc))->semantic(sc), ve->var);
goto Lagain;
}
else if (sc->intypeof != 1 && sc->parent->isFuncDeclaration())
else if (isNeedThisScope(sc, f))
{
error("need 'this' for '%s' of type '%s'", f->toChars(), f->type->toChars());
return new ErrorExp();
Expand All @@ -8450,9 +8457,11 @@ Expression *CallExp::semantic(Scope *sc)

ethis = NULL;

ve->var = f;
// ve->hasOverloads = 0;
ve->type = f->type;
if (ve->hasOverloads)
{
e1 = new VarExp(ve->loc, f, 0);
e1->type = f->type;
}
t1 = f->type;
}
assert(t1->ty == Tfunction);
Expand Down
2 changes: 2 additions & 0 deletions src/struct.c
Expand Up @@ -81,6 +81,7 @@ void AggregateDeclaration::semantic2(Scope *sc)
if (members)
{
sc = sc->push(this);
sc->parent = this;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
Expand All @@ -97,6 +98,7 @@ void AggregateDeclaration::semantic3(Scope *sc)
if (members)
{
sc = sc->push(this);
sc->parent = this;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
Expand Down
34 changes: 34 additions & 0 deletions test/runnable/testrightthis.d
Expand Up @@ -479,6 +479,39 @@ void test9619()
}
}

/********************************************************/
// 9633

class Foo9633
{
void baz() {}
void bar()
{
// CallExp::e1->op == TOKvar
static assert(!compilesWithoutThis9633!baz);
}
void vaz()()
{
static class C
{
// CallExp::e1->op == TOKtemplate
static assert(!__traits(compiles, vaz()));
}
}
}

template compilesWithoutThis9633(alias F)
{
enum bool compilesWithoutThis9633 = __traits(compiles, F());
}

void test9633()
{
auto foo = new Foo9633;
foo.bar();
foo.vaz();
}

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

int main()
Expand All @@ -491,6 +524,7 @@ int main()
test6();
test7();
test9619();
test9633();

printf("Success\n");
return 0;
Expand Down

0 comments on commit 0679c4c

Please sign in to comment.