diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index fad6b9cb48..80caadb009 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -2542,6 +2542,10 @@ public: bool isCrtCtor(bool v); bool isCrtDtor() const; bool isCrtDtor(bool v); + bool hasEscapingSiblings() const; + bool hasEscapingSiblings(bool v); + bool computedEscapingSiblings() const; + bool computedEscapingSiblings(bool v); private: uint32_t bitFields; public: diff --git a/compiler/src/dmd/func.d b/compiler/src/dmd/func.d index cf3e115452..3789d7a544 100644 --- a/compiler/src/dmd/func.d +++ b/compiler/src/dmd/func.d @@ -217,6 +217,8 @@ private struct FUNCFLAG bool hasAlwaysInlines; /// Contains references to functions that must be inlined bool isCrtCtor; /// Has attribute pragma(crt_constructor) bool isCrtDtor; /// Has attribute pragma(crt_destructor) + bool hasEscapingSiblings;/// Has sibling functions that escape + bool computedEscapingSiblings; /// `hasEscapingSiblings` has been computed } /*********************************************************** @@ -1980,6 +1982,7 @@ extern (C++) class FuncDeclaration : Declaration if (!sc.intypeof && !(sc.flags & SCOPE.compile)) { siblingCallers.push(fdthis); + computedEscapingSiblings = false; } } } @@ -2029,8 +2032,7 @@ extern (C++) class FuncDeclaration : Declaration * is already set to `true` upon entering this function when the * struct/class refers to a local variable and a closure is needed. */ - - //printf("FuncDeclaration::needsClosure() %s\n", toChars()); + //printf("FuncDeclaration::needsClosure() %s\n", toPrettyChars()); if (requiresClosure) goto Lyes; @@ -2107,7 +2109,7 @@ extern (C++) class FuncDeclaration : Declaration */ extern (C++) final bool checkClosure() { - //printf("checkClosure() %s\n", toChars()); + //printf("checkClosure() %s\n", toPrettyChars()); if (!needsClosure()) return false; @@ -3625,6 +3627,9 @@ private bool checkEscapingSiblings(FuncDeclaration f, FuncDeclaration outerFunc, FuncDeclaration f; } + if (f.computedEscapingSiblings) + return f.hasEscapingSiblings; + PrevSibling ps; ps.p = cast(PrevSibling*)p; ps.f = f; @@ -3666,6 +3671,8 @@ private bool checkEscapingSiblings(FuncDeclaration f, FuncDeclaration outerFunc, prev = prev.p; } } + f.hasEscapingSiblings = bAnyClosures; + f.computedEscapingSiblings = true; //printf("\t%d\n", bAnyClosures); return bAnyClosures; } diff --git a/compiler/test/compilable/test23676.d b/compiler/test/compilable/test23676.d new file mode 100644 index 0000000000..91a73b9de8 --- /dev/null +++ b/compiler/test/compilable/test23676.d @@ -0,0 +1,16 @@ +// Issue 23676 - Static foreach hangs compilation for some time +// https://issues.dlang.org/show_bug.cgi?id=23676 + +void f() +{ + int i; + void g(int I)() + { + static foreach(j; 0..11) + { + i++; + g!j(); + } + } + g!0; +}