Permalink
Browse files

fix Issue 8832 - Segfault when accessing range returned by function t…

…hat has delegate referencing local variables
  • Loading branch information...
1 parent c1a0bfe commit 63bba9d02ad4ff783c10c543c2c9ea4e91248873 @WalterBright WalterBright committed Jan 29, 2013
Showing with 58 additions and 5 deletions.
  1. +1 −0 src/dsymbol.c
  2. +27 −5 src/func.c
  3. +30 −0 test/runnable/nested.d
View
@@ -259,6 +259,7 @@ Dsymbol *Dsymbol::pastMixin()
/**********************************
* Use this instead of toParent() when looking for the
* 'this' pointer of the enclosing function/class.
+ * This skips over both TemplateInstance's and TemplateMixin's.
*/
Dsymbol *Dsymbol::toParent2()
View
@@ -3257,22 +3257,32 @@ const char *FuncDeclaration::kind()
return "function";
}
+/*********************************************
+ * In the current function, we are calling 'this' function.
+ * 1. Check to see if the current function can call 'this' function, issue error if not.
+ * 2. If the current function is not the parent of 'this' function, then add
+ * the current function to the list of siblings of 'this' function.
+ * 3. If the current function is a literal, and it's accessing an uplevel scope,
+ * then mark it as a delegate.
+ */
+
void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
{
- //printf("FuncDeclaration::checkNestedReference() %s\n", toChars());
+ //printf("FuncDeclaration::checkNestedReference() %s\n", toPrettyChars());
if (parent && parent != sc->parent && this->isNested() &&
this->ident != Id::require && this->ident != Id::ensure)
{
// The function that this function is in
- FuncDeclaration *fdv = toParent()->isFuncDeclaration();
+ FuncDeclaration *fdv2 = toParent2()->isFuncDeclaration();
+
// The current function
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
//printf("this = %s in [%s]\n", this->toChars(), this->loc.toChars());
//printf("fdv = %s in [%s]\n", fdv->toChars(), fdv->loc.toChars());
//printf("fdthis = %s in [%s]\n", fdthis->toChars(), fdthis->loc.toChars());
- if (fdv && fdthis && fdv != fdthis)
+ if (fdv2 && fdthis && fdv2 != fdthis)
{
// Add this function to the list of those which called us
if (fdthis != this)
@@ -3283,14 +3293,24 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
found = true;
}
if (!found)
+ {
+ //printf("\tadding sibling %s\n", fdthis->toPrettyChars());
siblingCallers.push(fdthis);
+ }
}
+ }
+ FuncDeclaration *fdv = toParent()->isFuncDeclaration();
+ fdv = toParent()->isFuncDeclaration();
+ if (fdv && fdthis && fdv != fdthis)
+ {
int lv = fdthis->getLevel(loc, sc, fdv);
if (lv == -1)
- return; // OK
+ return; // downlevel call
if (lv == 0)
- return; // OK
+ return; // same level call
+
+ // Uplevel call
// BUG: may need to walk up outer scopes like Declaration::checkNestedReference() does
@@ -3330,6 +3350,7 @@ void markAsNeedingClosure(Dsymbol *f, FuncDeclaration *outerFunc)
*/
bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc)
{
+ //printf("checkEscapingSiblings(f = %s, outerfunc = %s)\n", f->toChars(), outerFunc->toChars());
bool bAnyClosures = false;
for (int i = 0; i < f->siblingCallers.dim; ++i)
{
@@ -3341,6 +3362,7 @@ bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc)
}
bAnyClosures |= checkEscapingSiblings(g, outerFunc);
}
+ //printf("\t%d\n", bAnyClosures);
return bAnyClosures;
}
View
@@ -2192,6 +2192,35 @@ void test8774() {
/*******************************************/
+int Bug8832(alias X)()
+{
+ return X();
+}
+
+int delegate() foo8832()
+{
+ int stack;
+ int heap = 3;
+
+ int nested_func()
+ {
+ ++heap;
+ return heap;
+ }
+ return delegate int() { return Bug8832!(nested_func); };
+}
+
+void test8832()
+{
+ auto z = foo8832();
+ auto p = foo8832();
+ assert(z() == 4);
+ p();
+ assert(z() == 5);
+}
+
+/*******************************************/
+
int main()
{
test1();
@@ -2272,6 +2301,7 @@ int main()
test9036();
// test8863();
test8774();
+ test8832();
printf("Success\n");
return 0;

0 comments on commit 63bba9d

Please sign in to comment.