Bug 3912 – pure static nested functions are not recognized as pure

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2010-03-09T04:29:00Z
Last change time
2015-06-09T01:27:39Z
Keywords
patch, rejects-valid
Assigned to
nobody
Creator
clugdbug

Comments

Comment #0 by clugdbug — 2010-03-09T04:29:59Z
This bug was reported in a comment in bug 3835 ("fragile CTFE"), but it does not involve CTFE, so I've created a new bug for it. ===== pure int genFactorials(int n) { static pure int factorial(int n) { if (n==2) return 1; return factorial(2); } return factorial(n); } ============================ bug.d(7): Error: pure function 'factorial' cannot call impure function 'factor ial' bug.d(9): Error: pure function 'genFactorials' cannot call impure function 'fa ctorial'
Comment #1 by clugdbug — 2010-03-10T13:48:03Z
This was a mistake in my patch for bug 2804 (one of my first ever patches). I had only considered one level of nesting. I've also changed the error message so that it names the pure function, not the nested impure one. There's also some error messages with spurious newlines in them. Here's a test case which should fail: --- void f() pure { void g() { void h() pure { void i() { } void j() { i(); g(); } } } } ------ PATCH against DMD2.041. Expression::checkPurity(), around line 1280. Index: expression.c =================================================================== --- expression.c (revision 413) +++ expression.c (working copy) @@ -1296,17 +1296,31 @@ * i() can call h() and g() but not f() */ FuncDeclaration *outerfunc = sc->func; - while (outerfunc->toParent2() && outerfunc->toParent2()->isFuncDeclaration()) + // Find the closest pure parent of the calling function + while (outerfunc->toParent2() && !outerfunc->isPure() + && outerfunc->toParent2()->isFuncDeclaration() ) { outerfunc = outerfunc->toParent2()->isFuncDeclaration(); } - if (outerfunc->isPure() && !sc->intypeof && (!f->isNested() && !f->isPure())) - error("pure function '%s' cannot call impure function '%s'\n", - sc->func->toChars(), f->toChars()); + // Find the closest pure parent of the called function + FuncDeclaration *calledparent = f; + while (calledparent->toParent2() && !calledparent->isPure() + && calledparent->toParent2()->isFuncDeclaration() ) + { + calledparent = calledparent->toParent2()->isFuncDeclaration(); + } + // If the caller has a pure parent, then either the called func must be pure, + // OR, they must have the same pure parent. + if (outerfunc->isPure() && !sc->intypeof && + !(f->isPure() || (calledparent == outerfunc))) + { + error("pure function '%s' cannot call impure function '%s'", + outerfunc->toChars(), f->toChars()); + } } #else if (sc->func && sc->func->isPure() && !sc->intypeof && !f->isPure()) - error("pure function '%s' cannot call impure function '%s'\n", + error("pure function '%s' cannot call impure function '%s'", sc->func->toChars(), f->toChars()); #endif } @@ -1315,7 +1329,7 @@ { if (sc->func && sc->func->isSafe() && !sc->intypeof && !f->isSafe() && !f->isTrusted()) - error("safe function '%s' cannot call system function '%s'\n", + error("safe function '%s' cannot call system function '%s'", sc->func->toChars(), f->toChars()); } #endif
Comment #2 by bugzilla — 2010-03-12T20:26:01Z
changeset 414
Comment #3 by clugdbug — 2010-03-27T07:49:36Z
Fixed DMD2.042.