changeset 639:8aebdf56c455

Move check for access of context for nested class from backend into frontend.
author Christian Kamm <kamm incasoftware de>
date Thu, 02 Oct 2008 23:12:19 +0200
parents 94b01f15814f
children c2a342b5d8e5
files dmd/declaration.h dmd/expression.c gen/classes.cpp gen/llvmhelpers.cpp
diffstat 4 files changed, 27 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/declaration.h	Thu Oct 02 03:38:29 2008 +0200
+++ b/dmd/declaration.h	Thu Oct 02 23:12:19 2008 +0200
@@ -636,7 +636,12 @@
     FuncDeclaration *isFuncDeclaration() { return this; }
 
     // llvmdc stuff
+
+    // vars declared in this function that nested funcs reference
+    // is this is not empty, nestedFrameRef is set and these VarDecls
+    // probably have nestedref set too, see VarDeclaration::checkNestedReference
     std::set<VarDeclaration*> nestedVars;
+
     std::string intrinsicName;
 
     bool isIntrinsic();
--- a/dmd/expression.c	Thu Oct 02 03:38:29 2008 +0200
+++ b/dmd/expression.c	Thu Oct 02 23:12:19 2008 +0200
@@ -3370,6 +3370,7 @@
 	     */
 	    Dsymbol *s = cd->toParent2();
 	    ClassDeclaration *cdn = s->isClassDeclaration();
+	    FuncDeclaration *fdn = s->isFuncDeclaration();
 
 	    //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
 	    if (cdn)
@@ -3421,6 +3422,22 @@
 	    }
 	    else if (thisexp)
 		error("e.new is only for allocating nested classes");
+	    else if (fdn)
+	    {
+		// make sure the parent context fdn of cd is reachable from sc
+		for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
+		{
+		    if (fdn == sp)
+			break;
+		    FuncDeclaration *fsp = sp ? sp->isFuncDeclaration() : NULL;
+		    if (!sp || (fsp && fsp->isStatic()))
+		    {
+			error("outer function context of %s is needed to 'new' nested class %s", fdn->toPrettyChars(), cd->toPrettyChars());
+			break;
+		    }
+		}
+		
+	    }
 	}
 	else if (thisexp)
 	    error("e.new is only for allocating nested classes");
--- a/gen/classes.cpp	Thu Oct 02 03:38:29 2008 +0200
+++ b/gen/classes.cpp	Thu Oct 02 23:12:19 2008 +0200
@@ -842,12 +842,6 @@
         Logger::println("Resolving nested context");
         LOG_SCOPE;
 
-        if (gIR->func()->decl->isStatic())
-        {
-            newexp->error("function %s is static and cannot access nested class %s", gIR->func()->decl->toPrettyChars(), tc->sym->toPrettyChars());
-            fatal();
-        }
-
         // get context
         LLValue* nest = DtoNestedContext(loc, tc->sym);
 
--- a/gen/llvmhelpers.cpp	Thu Oct 02 03:38:29 2008 +0200
+++ b/gen/llvmhelpers.cpp	Thu Oct 02 23:12:19 2008 +0200
@@ -390,11 +390,15 @@
     LOG_SCOPE;
 
     IrFunction* irfunc = gIR->func();
-    
+
+    // if this func has its own vars that are accessed by nested funcs
+    // use its own context
     if (irfunc->nestedVar)
         return irfunc->nestedVar;
+    // otherwise, it may have gotten a context from the caller
     else if (irfunc->nestArg)
         return irfunc->nestArg;
+    // or just have a this argument
     else if (irfunc->thisArg)
     {
         ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();