Skip to content

Commit

Permalink
Propagate error in nestedRefs check
Browse files Browse the repository at this point in the history
It's necessary to avoid redundant errors in fail_compilation/diag0148.d.
  • Loading branch information
9rnsr committed Jan 26, 2015
1 parent 724b6f3 commit f4c2c4b
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 34 deletions.
12 changes: 10 additions & 2 deletions src/declaration.c
Expand Up @@ -1728,7 +1728,7 @@ void VarDeclaration::checkCtorConstInit()
* rather than the current one.
*/

void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
bool VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
{
//printf("VarDeclaration::checkNestedReference() %s\n", toChars());
if (parent && !isDataseg() && parent != sc->parent &&
Expand Down Expand Up @@ -1763,7 +1763,11 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
//printf("\tfdthis = %s\n", fdthis->toChars());

if (loc.filename)
fdthis->getLevel(loc, sc, fdv);
{
int lv = fdthis->getLevel(loc, sc, fdv);
if (lv == -2) // error
return false;
}

// Function literals from fdthis to fdv must be delegates
for (Dsymbol *s = fdthis; s && s != fdv; s = s->toParent2())
Expand Down Expand Up @@ -1806,10 +1810,14 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
//printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
// __dollar creates problems because it isn't a real variable Bugzilla 3326
if (ident == Id::dollar)
{
::error(loc, "cannnot use $ inside a function literal");
return false;
}
}
}
}
return true;
}

/****************************
Expand Down
4 changes: 2 additions & 2 deletions src/declaration.h
Expand Up @@ -280,7 +280,7 @@ class VarDeclaration : public Declaration
ExpInitializer *getExpInitializer();
Expression *getConstInitializer(bool needFullType = true);
void checkCtorConstInit();
void checkNestedReference(Scope *sc, Loc loc);
bool checkNestedReference(Scope *sc, Loc loc);
Dsymbol *toAlias();
// Eliminate need for dynamic_cast
VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; }
Expand Down Expand Up @@ -649,7 +649,7 @@ class FuncDeclaration : public Declaration
virtual bool addPostInvariant();
const char *kind();
FuncDeclaration *isUnique();
void checkNestedReference(Scope *sc, Loc loc);
bool checkNestedReference(Scope *sc, Loc loc);
bool needsClosure();
bool hasNestedFrameRefs();
void buildResultVar(Scope *sc, Type *tret);
Expand Down
36 changes: 24 additions & 12 deletions src/delegatize.c
Expand Up @@ -33,7 +33,7 @@

bool walkPostorder(Expression *e, StoppableVisitor *v);
void lambdaSetParent(Expression *e, Scope *sc);
void lambdaCheckForNestedRef(Expression *e, Scope *sc);
bool lambdaCheckForNestedRef(Expression *e, Scope *sc);

Expression *toDelegate(Expression *e, Scope *sc)
{
Expand All @@ -50,9 +50,12 @@ Expression *toDelegate(Expression *e, Scope *sc)
sc = sc->push();
sc->parent = fld; // set current function to be the delegate
lambdaSetParent(e, sc);
lambdaCheckForNestedRef(e, sc);
bool r = lambdaCheckForNestedRef(e, sc);
sc = sc->pop();

if (!r)
return new ErrorExp();

Statement *s;
if (t->ty == Tvoid)
s = new ExpStatement(loc, e);
Expand Down Expand Up @@ -110,14 +113,20 @@ void lambdaSetParent(Expression *e, Scope *sc)

/*******************************************
* Look for references to variables in a scope enclosing the new function literal.
* Returns false if error occurs.
*/
void lambdaCheckForNestedRef(Expression *e, Scope *sc)
bool lambdaCheckForNestedRef(Expression *e, Scope *sc)
{
class LambdaCheckForNestedRef : public StoppableVisitor
{
Scope *sc;
public:
LambdaCheckForNestedRef(Scope *sc) : sc(sc) {}
Scope *sc;
bool result;

LambdaCheckForNestedRef(Scope *sc)
: sc(sc), result(true)
{
}

void visit(Expression *)
{
Expand All @@ -127,29 +136,31 @@ void lambdaCheckForNestedRef(Expression *e, Scope *sc)
{
VarDeclaration *v = e->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, Loc());
result = v->checkNestedReference(sc, Loc());
}

void visit(VarExp *e)
{
VarDeclaration *v = e->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, Loc());
result = v->checkNestedReference(sc, Loc());
}

void visit(ThisExp *e)
{
VarDeclaration *v = e->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, Loc());
result = v->checkNestedReference(sc, Loc());
}

void visit(DeclarationExp *e)
{
VarDeclaration *v = e->declaration->isVarDeclaration();
if (v)
{
v->checkNestedReference(sc, Loc());
result = v->checkNestedReference(sc, Loc());
if (!result)
return;

/* Some expressions cause the frontend to create a temporary.
* For example, structs with cpctors replace the original
Expand All @@ -163,13 +174,14 @@ void lambdaCheckForNestedRef(Expression *e, Scope *sc)
if (v->init && v->init->isExpInitializer())
{
Expression *ie = v->init->toExpression();
lambdaCheckForNestedRef(ie, sc);
result = lambdaCheckForNestedRef(ie, sc);
}
}
}
};

LambdaCheckForNestedRef lcnr(sc);
walkPostorder(e, &lcnr);
LambdaCheckForNestedRef v(sc);
walkPostorder(e, &v);
return v.result;
}

34 changes: 22 additions & 12 deletions src/expression.c
Expand Up @@ -3439,7 +3439,8 @@ Expression *ThisExp::semantic(Scope *sc)
var = fd->vthis;
assert(var->parent);
type = var->type;
var->isVarDeclaration()->checkNestedReference(sc, loc);
if (!var->isVarDeclaration()->checkNestedReference(sc, loc))
return new ErrorExp();
if (!sc->intypeof)
sc->callSuper |= CSXthis;
return this;
Expand Down Expand Up @@ -3544,7 +3545,8 @@ Expression *SuperExp::semantic(Scope *sc)
type = type->castMod(var->type->mod);
}

var->isVarDeclaration()->checkNestedReference(sc, loc);
if (!var->isVarDeclaration()->checkNestedReference(sc, loc))
return new ErrorExp();

if (!sc->intypeof)
sc->callSuper |= CSXsuper;
Expand Down Expand Up @@ -5053,12 +5055,16 @@ Expression *SymOffExp::semantic(Scope *sc)
//var->semantic(sc);
if (!type)
type = var->type->pointerTo();
VarDeclaration *v = var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, loc);
FuncDeclaration *f = var->isFuncDeclaration();
if (f)
f->checkNestedReference(sc, loc);
if (VarDeclaration *v = var->isVarDeclaration())
{
if (!v->checkNestedReference(sc, loc))
return new ErrorExp();
}
else if (FuncDeclaration *f = var->isFuncDeclaration())
{
if (!f->checkNestedReference(sc, loc))
return new ErrorExp();
}
return this;
}

Expand Down Expand Up @@ -5125,11 +5131,13 @@ Expression *VarExp::semantic(Scope *sc)
if (VarDeclaration *vd = var->isVarDeclaration())
{
hasOverloads = 0;
vd->checkNestedReference(sc, loc);
if (!vd->checkNestedReference(sc, loc))
return new ErrorExp();
}
else if (FuncDeclaration *fd = var->isFuncDeclaration())
{
fd->checkNestedReference(sc, loc);
if (!fd->checkNestedReference(sc, loc))
return new ErrorExp();
}
else if (OverDeclaration *od = var->isOverDeclaration())
{
Expand Down Expand Up @@ -8733,7 +8741,8 @@ Expression *CallExp::semantic(Scope *sc)
checkPurity(sc, f);
checkSafety(sc, f);
checkNogc(sc, f);
f->checkNestedReference(sc, loc);
if (!f->checkNestedReference(sc, loc))
return new ErrorExp();
}
else if (sc->func && sc->intypeof != 1 && !(sc->flags & SCOPEctfe))
{
Expand Down Expand Up @@ -8820,7 +8829,8 @@ Expression *CallExp::semantic(Scope *sc)
checkPurity(sc, f);
checkSafety(sc, f);
checkNogc(sc, f);
f->checkNestedReference(sc, loc);
if (!f->checkNestedReference(sc, loc))
return new ErrorExp();
accessCheck(loc, sc, NULL, f);

ethis = NULL;
Expand Down
13 changes: 9 additions & 4 deletions src/func.c
Expand Up @@ -3320,8 +3320,9 @@ AggregateDeclaration *FuncDeclaration::isMember2()
* Error if this cannot call fd.
* Returns:
* 0 same level
* -1 increase nesting by 1 (fd is nested within 'this')
* >0 decrease nesting by number
* -1 increase nesting by 1 (fd is nested within 'this')
* -2 error
*/

int FuncDeclaration::getLevel(Loc loc, Scope *sc, FuncDeclaration *fd)
Expand Down Expand Up @@ -3381,6 +3382,7 @@ int FuncDeclaration::getLevel(Loc loc, Scope *sc, FuncDeclaration *fd)
// better diagnostics for static functions
::error(loc, "%s%s %s cannot access frame of function %s",
xstatic, kind(), toPrettyChars(), fd->toPrettyChars());
return -2;
}
return 1;
}
Expand Down Expand Up @@ -3963,7 +3965,7 @@ const char *FuncDeclaration::kind()
* then mark it as a delegate.
*/

void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
bool FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
{
//printf("FuncDeclaration::checkNestedReference() %s\n", toPrettyChars());
if (parent && parent != sc->parent && this->isNested() &&
Expand Down Expand Up @@ -4003,10 +4005,12 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
if (fdv && fdthis && fdv != fdthis)
{
int lv = fdthis->getLevel(loc, sc, fdv);
if (lv == -2)
return false; // error
if (lv == -1)
return; // downlevel call
return true; // downlevel call
if (lv == 0)
return; // same level call
return true; // same level call

// Uplevel call

Expand All @@ -4017,6 +4021,7 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
fld->tok = TOKdelegate;
}
}
return true;
}

/* For all functions between outerFunc and f, mark them as needing
Expand Down
3 changes: 2 additions & 1 deletion src/statement.c
Expand Up @@ -3938,7 +3938,8 @@ Statement *ReturnStatement::semantic(Scope *sc)
else
{
fd->buildResultVar(NULL, exp->type);
fd->vresult->checkNestedReference(sc, Loc());
bool r = fd->vresult->checkNestedReference(sc, Loc());
assert(r); // vresult should be always accessible

// Send out "case receiver" statement to the foreach.
// return vresult;
Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail12378.d
Expand Up @@ -53,9 +53,9 @@ fail_compilation/fail12378.d(143): instantiated from here: __lambda1!int
fail_compilation/fail12378.d(135): instantiated from here: MapResultI!((y0) => iota(2).mapI!((x0) => ANYTHING - GOES), Result)
fail_compilation/fail12378.d(62): instantiated from here: mapI!(Result)
fail_compilation/fail12378.d(143): Error: static function fail12378.testI.MapResultI!((y0) => iota(2).mapI!((x0) => ANYTHING - GOES), Result).MapResultI.front cannot access frame of function fail12378.testI
fail_compilation/fail12378.d(143): Error: static function fail12378.testI.MapResultI!((y0) => iota(2).mapI!((x0) => ANYTHING - GOES), Result).MapResultI.front cannot access frame of function fail12378.testI
---
*/

void testI()
{
auto r =
Expand Down

0 comments on commit f4c2c4b

Please sign in to comment.