From 808cba5c4a8f78ca172ab339b942dbab1ad1bbe6 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Sun, 6 Oct 2024 07:30:39 +0800 Subject: [PATCH] move `checkNestedFuncReference` to expressionssem.d and make private --- compiler/src/dmd/expressionsem.d | 84 ++++++++++++++++++++++++++++++++ compiler/src/dmd/funcsem.d | 84 -------------------------------- 2 files changed, 84 insertions(+), 84 deletions(-) diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index 09e6795a447..2183d611618 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -17368,3 +17368,87 @@ private Expression expandInitializer(VarDeclaration vd, Loc loc) e.loc = loc; // for better error message return e; } + +/********************************************* + * In the current function 'sc.func', we are calling 'fd'. + * 1. Check to see if the current function can call 'fd' , issue error if not. + * 2. If the current function is not the parent of 'fd' , then add + * the current function to the list of siblings of 'fd' . + * 3. If the current function is a literal, and it's accessing an uplevel scope, + * then mark it as a delegate. + * Returns true if error occurs. + */ +private bool checkNestedFuncReference(FuncDeclaration fd, Scope* sc, const ref Loc loc) +{ + //printf("FuncDeclaration::checkNestedFuncReference() %s\n", toPrettyChars()); + if (auto fld = fd.isFuncLiteralDeclaration()) + { + if (fld.tok == TOK.reserved) + { + fld.tok = TOK.function_; + fld.vthis = null; + } + } + if (!fd.parent || fd.parent == sc.parent) + return false; + if (fd.ident == Id.require || fd.ident == Id.ensure) + return false; + if (!fd.isThis() && !fd.isNested()) + return false; + // The current function + FuncDeclaration fdthis = sc.parent.isFuncDeclaration(); + if (!fdthis) + return false; // out of function scope + Dsymbol p = fd.toParentLocal(); + Dsymbol p2 = fd.toParent2(); + // Function literals from fdthis to p must be delegates + ensureStaticLinkTo(fdthis, p); + if (p != p2) + ensureStaticLinkTo(fdthis, p2); + if (!fd.isNested()) + return false; + + // The function that this function is in + bool checkEnclosing(FuncDeclaration fdv) + { + if (!fdv) + return false; + if (fdv == fdthis) + return false; + //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()); + // Add this function to the list of those which called us + if (fdthis != fd) + { + bool found = false; + for (size_t i = 0; i < fd.siblingCallers.length; ++i) + { + if (fd.siblingCallers[i] == fdthis) + found = true; + } + if (!found) + { + //printf("\tadding sibling %s to %s\n", fdthis.toPrettyChars(), toPrettyChars()); + if (!sc.intypeof && !sc.traitsCompiles) + { + fd.siblingCallers.push(fdthis); + fd.computedEscapingSiblings = false; + } + } + } + const lv = fdthis.getLevelAndCheck(loc, sc, fdv, fd); + if (lv == fd.LevelError) + return true; // error + if (lv == -1) + return false; // downlevel call + if (lv == 0) + return false; // same level call + return false; // Uplevel call + } + if (checkEnclosing(p.isFuncDeclaration())) + return true; + if (checkEnclosing(p == p2 ? null : p2.isFuncDeclaration())) + return true; + return false; +} diff --git a/compiler/src/dmd/funcsem.d b/compiler/src/dmd/funcsem.d index 3765deb0d77..2ac3ed41c49 100644 --- a/compiler/src/dmd/funcsem.d +++ b/compiler/src/dmd/funcsem.d @@ -2263,90 +2263,6 @@ bool canInferAttributes(FuncDeclaration fd, Scope* sc) return false; } -/********************************************* - * In the current function 'sc.func', we are calling 'fd'. - * 1. Check to see if the current function can call 'fd' , issue error if not. - * 2. If the current function is not the parent of 'fd' , then add - * the current function to the list of siblings of 'fd' . - * 3. If the current function is a literal, and it's accessing an uplevel scope, - * then mark it as a delegate. - * Returns true if error occurs. - */ -bool checkNestedFuncReference(FuncDeclaration fd, Scope* sc, const ref Loc loc) -{ - //printf("FuncDeclaration::checkNestedFuncReference() %s\n", toPrettyChars()); - if (auto fld = fd.isFuncLiteralDeclaration()) - { - if (fld.tok == TOK.reserved) - { - fld.tok = TOK.function_; - fld.vthis = null; - } - } - if (!fd.parent || fd.parent == sc.parent) - return false; - if (fd.ident == Id.require || fd.ident == Id.ensure) - return false; - if (!fd.isThis() && !fd.isNested()) - return false; - // The current function - FuncDeclaration fdthis = sc.parent.isFuncDeclaration(); - if (!fdthis) - return false; // out of function scope - Dsymbol p = fd.toParentLocal(); - Dsymbol p2 = fd.toParent2(); - // Function literals from fdthis to p must be delegates - ensureStaticLinkTo(fdthis, p); - if (p != p2) - ensureStaticLinkTo(fdthis, p2); - if (!fd.isNested()) - return false; - - // The function that this function is in - bool checkEnclosing(FuncDeclaration fdv) - { - if (!fdv) - return false; - if (fdv == fdthis) - return false; - //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()); - // Add this function to the list of those which called us - if (fdthis != fd) - { - bool found = false; - for (size_t i = 0; i < fd.siblingCallers.length; ++i) - { - if (fd.siblingCallers[i] == fdthis) - found = true; - } - if (!found) - { - //printf("\tadding sibling %s to %s\n", fdthis.toPrettyChars(), toPrettyChars()); - if (!sc.intypeof && !sc.traitsCompiles) - { - fd.siblingCallers.push(fdthis); - fd.computedEscapingSiblings = false; - } - } - } - const lv = fdthis.getLevelAndCheck(loc, sc, fdv, fd); - if (lv == fd.LevelError) - return true; // error - if (lv == -1) - return false; // downlevel call - if (lv == 0) - return false; // same level call - return false; // Uplevel call - } - if (checkEnclosing(p.isFuncDeclaration())) - return true; - if (checkEnclosing(p == p2 ? null : p2.isFuncDeclaration())) - return true; - return false; -} - /**************************************************** * Check whether result variable can be built. * Returns: