From 1fe1cac81bb4c77d5a0b06e77ccf0dc21b3c9d7f Mon Sep 17 00:00:00 2001 From: Matthew Qiu <93230055+MatthewQiu-5@users.noreply.github.com> Date: Tue, 15 Apr 2025 07:46:48 -0400 Subject: [PATCH] Moved VarDeclaration.checkNestedReference to funcsem (#21237) --- compiler/src/dmd/declaration.d | 78 ---------------------------------- compiler/src/dmd/delegatize.d | 1 + compiler/src/dmd/funcsem.d | 77 +++++++++++++++++++++++++++++++++ compiler/src/dmd/iasmdmd.d | 1 + 4 files changed, 79 insertions(+), 78 deletions(-) diff --git a/compiler/src/dmd/declaration.d b/compiler/src/dmd/declaration.d index 4a1ec9f048..25e5c31dcc 100644 --- a/compiler/src/dmd/declaration.d +++ b/compiler/src/dmd/declaration.d @@ -27,7 +27,6 @@ import dmd.dtemplate; import dmd.errors; import dmd.expression; import dmd.func; -import dmd.funcsem : getLevelAndCheck; import dmd.globals; import dmd.gluelayer; import dmd.hdrgen; @@ -1084,83 +1083,6 @@ extern (C++) class VarDeclaration : Declaration return e; } - /************************************ - * Check to see if this variable is actually in an enclosing function - * rather than the current one. - * Update nestedrefs[], closureVars[] and outerVars[]. - * Returns: true if error occurs. - */ - extern (D) final bool checkNestedReference(Scope* sc, Loc loc) - { - //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); - if (sc.intypeof == 1 || sc.ctfe) - return false; - if (!parent || parent == sc.parent) - return false; - if (isDataseg() || (storage_class & STC.manifest)) - return false; - - // The current function - FuncDeclaration fdthis = sc.parent.isFuncDeclaration(); - if (!fdthis) - return false; // out of function scope - - Dsymbol p = toParent2(); - - // Function literals from fdthis to p must be delegates - ensureStaticLinkTo(fdthis, p); - - // The function that this variable is in - FuncDeclaration fdv = p.isFuncDeclaration(); - if (!fdv || fdv == fdthis) - return false; - - // Add fdthis to nestedrefs[] if not already there - if (!nestedrefs.contains(fdthis)) - nestedrefs.push(fdthis); - - //printf("\tfdv = %s\n", fdv.toChars()); - //printf("\tfdthis = %s\n", fdthis.toChars()); - if (loc.isValid()) - { - if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError) - return true; - } - - // Add this VarDeclaration to fdv.closureVars[] if not already there - if (!sc.intypeof && !sc.traitsCompiles && - // https://issues.dlang.org/show_bug.cgi?id=17605 - (fdv.skipCodegen || !fdthis.skipCodegen)) - { - if (!fdv.closureVars.contains(this)) - fdv.closureVars.push(this); - } - - if (!fdthis.outerVars.contains(this)) - fdthis.outerVars.push(this); - - //printf("fdthis is %s\n", fdthis.toChars()); - //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars()); - // __dollar creates problems because it isn't a real variable - // https://issues.dlang.org/show_bug.cgi?id=3326 - if (ident == Id.dollar) - { - .error(loc, "cannnot use `$` inside a function literal"); - return true; - } - if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759 - { - ExpInitializer ez = _init.isExpInitializer(); - assert(ez); - Expression e = ez.exp; - if (e.op == EXP.construct || e.op == EXP.blit) - e = (cast(AssignExp)e).e2; - return lambdaCheckForNestedRef(e, sc); - } - - return false; - } - override final Dsymbol toAlias() { //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); diff --git a/compiler/src/dmd/delegatize.d b/compiler/src/dmd/delegatize.d index 344130b5e3..1f5dca66b5 100644 --- a/compiler/src/dmd/delegatize.d +++ b/compiler/src/dmd/delegatize.d @@ -21,6 +21,7 @@ import dmd.dsymbol; import dmd.expression; import dmd.expressionsem; import dmd.func; +import dmd.funcsem : checkNestedReference; import dmd.init; import dmd.initsem; import dmd.location; diff --git a/compiler/src/dmd/funcsem.d b/compiler/src/dmd/funcsem.d index a7fc488fca..a02d9b7781 100644 --- a/compiler/src/dmd/funcsem.d +++ b/compiler/src/dmd/funcsem.d @@ -3702,3 +3702,80 @@ Dsymbol isUnique(OverDeclaration od) }); return result; } + +/************************************ +* Check to see if this variable is actually in an enclosing function +* rather than the current one. +* Update nestedrefs[], closureVars[] and outerVars[]. +* Returns: true if error occurs. +*/ +extern (D) bool checkNestedReference(VarDeclaration vd, Scope* sc, Loc loc) +{ + //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); + if (sc.intypeof == 1 || sc.ctfe) + return false; + if (!vd.parent || vd.parent == sc.parent) + return false; + if (vd.isDataseg() || (vd.storage_class & STC.manifest)) + return false; + + // The current function + FuncDeclaration fdthis = sc.parent.isFuncDeclaration(); + if (!fdthis) + return false; // out of function scope + + Dsymbol p = vd.toParent2(); + + // Function literals from fdthis to p must be delegates + ensureStaticLinkTo(fdthis, p); + + // The function that this variable is in + FuncDeclaration fdv = p.isFuncDeclaration(); + if (!fdv || fdv == fdthis) + return false; + + // Add fdthis to nestedrefs[] if not already there + if (!vd.nestedrefs.contains(fdthis)) + vd.nestedrefs.push(fdthis); + + //printf("\tfdv = %s\n", fdv.toChars()); + //printf("\tfdthis = %s\n", fdthis.toChars()); + if (loc.isValid()) + { + if (fdthis.getLevelAndCheck(loc, sc, fdv, vd) == fdthis.LevelError) + return true; + } + + // Add this VarDeclaration to fdv.closureVars[] if not already there + if (!sc.intypeof && !sc.traitsCompiles && + // https://issues.dlang.org/show_bug.cgi?id=17605 + (fdv.skipCodegen || !fdthis.skipCodegen)) + { + if (!fdv.closureVars.contains(vd)) + fdv.closureVars.push(vd); + } + + if (!fdthis.outerVars.contains(vd)) + fdthis.outerVars.push(vd); + + //printf("fdthis is %s\n", fdthis.toChars()); + //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars()); + // __dollar creates problems because it isn't a real variable + // https://issues.dlang.org/show_bug.cgi?id=3326 + if (vd.ident == Id.dollar) + { + .error(loc, "cannnot use `$` inside a function literal"); + return true; + } + if (vd.ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759 + { + ExpInitializer ez = vd._init.isExpInitializer(); + assert(ez); + Expression e = ez.exp; + if (e.op == EXP.construct || e.op == EXP.blit) + e = (cast(AssignExp)e).e2; + return lambdaCheckForNestedRef(e, sc); + } + + return false; +} diff --git a/compiler/src/dmd/iasmdmd.d b/compiler/src/dmd/iasmdmd.d index 1e3c4142fc..fae74c3592 100644 --- a/compiler/src/dmd/iasmdmd.d +++ b/compiler/src/dmd/iasmdmd.d @@ -28,6 +28,7 @@ import dmd.dsymbol; import dmd.errors; import dmd.expression; import dmd.expressionsem; +import dmd.funcsem : checkNestedReference; import dmd.globals; import dmd.id; import dmd.identifier;