diff --git a/src/expression.c b/src/expression.c index 19ad6679f6a7..6a8f82549229 100644 --- a/src/expression.c +++ b/src/expression.c @@ -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. @@ -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()); @@ -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(); @@ -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)) { @@ -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(); @@ -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); diff --git a/src/struct.c b/src/struct.c index 2c71426c51ae..0557d17ab782 100644 --- a/src/struct.c +++ b/src/struct.c @@ -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]; @@ -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]; diff --git a/test/runnable/testrightthis.d b/test/runnable/testrightthis.d index 5fefd297309c..147751c0ab0c 100644 --- a/test/runnable/testrightthis.d +++ b/test/runnable/testrightthis.d @@ -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() @@ -491,6 +524,7 @@ int main() test6(); test7(); test9619(); + test9633(); printf("Success\n"); return 0;