title: Wrong code when combining anonymous and nested procedures
body: <p>I've got some unexpected access violations for Delphi code that I think is correct, but seems to be miscompiled. I can reduce it to</p>
  
  <pre><code>procedure Run(Proc: TProc);
  begin
    Proc;
  end;
  
  procedure Test;
  begin
    Run(
      procedure
      var
        S: PChar;
  
        procedure Nested;
        begin
          Run(
            procedure
            begin
            end);
          S := 'Hello, world!';
        end;
  
      begin
        Run(
          procedure
          begin
            S := 'Hello';
          end);
        Nested;
        ShowMessage(S);
      end);
  end;
  </code></pre>
  
  <p>What happens for me is that <code>S := 'Hello, world!'</code> is storing in the wrong location. Because of that, either an access violation is raised, or <code>ShowMessage(S)</code> shows "Hello" (and sometimes, an access violation is raised when freeing the objects used to implement anonymous procedures).</p>
  
  <p>I'm using Delphi XE, all updates installed.</p>
  
  <p>How can I know where this is going to cause problems? I know how to rewrite my code to avoid anonymous procedures, but I have trouble figuring out in precisely which situations they lead to wrong code, so I don't know where to avoid them.</p>
  
  <p>It would be interesting to me to know if this is fixed in later versions of Delphi, but nothing more than interesting, upgrading is not an option at this point.</p>
  
  <p>On QC, the most recent report I can find the similar <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=91876" rel="noreferrer">#91876</a>, but that is resolved in Delphi XE.</p>
  
  <p><strong>Update</strong>:</p>
  
  <p>Based on AlexSC's comments, with a slight modification:</p>
  
  <pre><code>...
  
        procedure Nested;
        begin
          Run(
            procedure
            begin
              S := S;
            end);
          S := 'Hello, world!';
        end;
  
  ...
  </code></pre>
  
  <p>does work.</p>
  
  <p>The generated machine code for</p>
  
  <pre><code>S := 'Hello, world!';
  </code></pre>
  
  <p>in the failing program is</p>
  
  <pre><code>ScratchForm.pas.44: S := 'Hello, world!';
  004BD971 B89CD94B00       mov eax,$004bd99c
  004BD976 894524           mov [ebp+$24],eax
  </code></pre>
  
  <p>whereas the correct version is</p>
  
  <pre><code>ScratchForm.pas.45: S := 'Hello, world!';
  004BD981 B8B0D94B00       mov eax,$004bd9b0
  004BD986 8B5508           mov edx,[ebp+$08]
  004BD989 8B52FC           mov edx,[edx-$04]
  004BD98C 89420C           mov [edx+$0c],eax
  </code></pre>
  
  <p>The generated code in the failing program is not seeing that <code>S</code> has been moved to a compiler-generated class, <code>[ebp+$24]</code> is <del>how outer local variables of nested methods are accessed</del> how local variables are accessed.</p>