Bug 2807 – Marking a nested function as 'pure' may cause bad code generations silently accepted

Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2009-04-06T08:03:00Z
Last change time
2015-06-09T01:18:03Z
Keywords
accepts-invalid, patch
Assigned to
bugzilla
Creator
clugdbug

Attachments

IDFilenameSummaryContent-TypeSize
3352807patch.patchPatch against 2.029. Includes patch for the related bug 2695, as well.text/plain2022

Comments

Comment #0 by clugdbug — 2009-04-06T08:03:34Z
The following assert fails, effectively generating bad code. My patch in #2804 doesn't fix this, but it does reduce the need for marking nested functions as pure. A nested function which is marked as pure should not be able to access variables from the enclosing scope. It's probably adequate to simply disallow 'pure' on nested functions for now. --- pure int double_sqr(int x) { int y = x; void do_sqr() pure { y *= y; } do_sqr(); return y; } void main(string[] args) { assert(double_sqr(10) == 100); }
Comment #1 by clugdbug — 2009-04-22T15:07:24Z
And here's a patch. This makes it safe to have nested pure functions. A nested pure function is only permitted to access its own variables, plus immutables and manifest constants from outer scopes. =================================================================== --- expression.c (revision 24) +++ expression.c (working copy) @@ -3994,12 +3994,21 @@ #if 1 if (sc->func) { FuncDeclaration *outerfunc=sc->func; + bool hasPureParent=false; while (outerfunc->toParent2() && outerfunc->toParent2()->isFuncDeclaration()) { + hasPureParent |= outerfunc->isPure(); outerfunc = outerfunc->toParent2()->isFuncDeclaration(); } - if (outerfunc->isPure() && !sc->intypeof && v->isDataseg() && !v->isInvariant()) + hasPureParent |= outerfunc->isPure(); + // If ANY of its enclosing functions are pure, it cannot do anything impure. + // If it is pure, it cannot access any mutable variables other than those inside itself. + if (hasPureParent && !sc->intypeof && v->isDataseg() && !v->isInvariant()) { error("pure function '%s' cannot access mutable static data '%s'", sc->func->toChars(), v->toChars()); - } + } else if (sc->func->isPure() && sc->parent!=v->parent && !sc->intypeof && !v->isInvariant() && !(v->storage_class & STCmanifest)) { + error("pure nested function '%s' cannot access mutable data '%s'", sc->func->toChars(), v->toChars()); + if (v->isEnumDeclaration()) error("enum"); + } + } #else if (sc->func && sc->func->isPure() && !sc->intypeof) {
Comment #2 by clugdbug — 2009-04-22T15:09:04Z
Created attachment 335 Patch against 2.029. Includes patch for the related bug 2695, as well.
Comment #3 by clugdbug — 2009-05-14T01:27:15Z
Fixed DMD2.030