<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">Hi Richard, John,<br>
      Done in r225624.<br>
      <pre class="moz-signature" cols="72">Best regards,
Alexey Bataev
=============
Software Engineer
Intel Compiler Team</pre>
      06.01.2015 8:45, John McCall пишет:<br>
    </div>
    <blockquote
      cite="mid:FB476822-9917-4451-BB80-0634B1E6935A@apple.com"
      type="cite">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <div>
        <blockquote type="cite" class="">
          <div class="">On Jan 5, 2015, at 7:05 AM, Richard Smith <<a
              moz-do-not-send="true" href="mailto:richard@metafoo.co.uk"
              class="">richard@metafoo.co.uk</a>> wrote:</div>
          <div class="">
            <div dir="ltr" class="">
              <div class="gmail_extra">
                <div class="gmail_quote">On Sun, Jan 4, 2015 at 7:57 PM,
                  John McCall <span dir="ltr" class=""><<a
                      moz-do-not-send="true"
                      href="mailto:rjmccall@apple.com" target="_blank"
                      class="">rjmccall@apple.com</a>></span> wrote:<br
                    class="">
                  <blockquote class="gmail_quote" style="margin:0px 0px
                    0px
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
                    <div style="word-wrap:break-word" class="">
                      <div class=""><span class="">
                          <blockquote type="cite" class="">
                            <div class="">On Jan 4, 2015, at 6:28 PM,
                              Richard Smith <<a
                                moz-do-not-send="true"
                                href="mailto:richard@metafoo.co.uk"
                                target="_blank" class="">richard@metafoo.co.uk</a>>
                              wrote:</div>
                            <div class="">
                              <p dir="ltr" class="">On 5 Jan 2015 02:08,
                                "John McCall" <<a
                                  moz-do-not-send="true"
                                  href="mailto:rjmccall@apple.com"
                                  target="_blank" class="">rjmccall@apple.com</a>>
                                wrote:<br class="">
                                >><br class="">
                                >> On Jan 4, 2015, at 1:11 AM,
                                Richard Smith <<a
                                  moz-do-not-send="true"
                                  href="mailto:richard@metafoo.co.uk"
                                  target="_blank" class="">richard@metafoo.co.uk</a>>
                                wrote:<br class="">
                                >> On Sat, Jan 3, 2015 at 1:46 PM,
                                John McCall <<a
                                  moz-do-not-send="true"
                                  href="mailto:rjmccall@apple.com"
                                  target="_blank" class="">rjmccall@apple.com</a>>
                                wrote:<br class="">
                                >>>><br class="">
                                >>>> On Jan 2, 2015, at 7:10
                                AM, Richard Smith <<a
                                  moz-do-not-send="true"
                                  href="mailto:richard@metafoo.co.uk"
                                  target="_blank" class="">richard@metafoo.co.uk</a>>
                                wrote:<br class="">
                                >>>> On Tue, Dec 16, 2014 at
                                12:01 AM, Alexey Bataev <<a
                                  moz-do-not-send="true"
                                  href="mailto:a.bataev@hotmail.com"
                                  target="_blank" class="">a.bataev@hotmail.com</a>>
                                wrote:<br class="">
                                >>>>><br class="">
                                >>>>> Author: abataev<br
                                  class="">
                                >>>>> Date: Tue Dec 16
                                02:01:48 2014<br class="">
                                >>>>> New Revision:
                                224329<br class="">
                                >>>>><br class="">
                                >>>>> URL: <a
                                  moz-do-not-send="true"
                                  href="http://llvm.org/viewvc/llvm-project?rev=224329&view=rev"
                                  target="_blank" class="">http://llvm.org/viewvc/llvm-project?rev=224329&view=rev</a><br
                                  class="">
                                >>>>> Log:<br class="">
                                >>>>> Renamed
                                RefersToEnclosingLocal bitfield to
                                RefersToCapturedVariable.<br class="">
                                >>>>> Bitfield
                                RefersToEnclosingLocal of
                                Stmt::DeclRefExprBitfields renamed to
                                RefersToCapturedVariable to reflect
                                latest changes introduced in commit
                                224323. Also renamed method
                                Expr::refersToEnclosingLocal() to
                                Expr::refersToCapturedVariable() and
                                comments for constant arguments.<br
                                  class="">
                                >>>>> No functional
                                changes.<br class="">
                                >>>><br class="">
                                >>>><br class="">
                                >>>> This seems like a bad
                                idea for me. It's incorrect: for a
                                lambda, the flag means that the
                                DeclRefExpr refers to an enclosing
                                local, and does *not* imply that the
                                variable is necessarily captured. This
                                confusion has already led to a bug
                                (fixed in r225060).<br class="">
                                >>><br class="">
                                >>><br class="">
                                >>> If that’s actually a useful
                                property to track, I have no complaint
                                about tracking the two things
                                separately.  I don’t think DRE is short
                                of bits.<br class="">
                                >><br class="">
                                >><br class="">
                                >> The problem is that we can't
                                reasonably track whether a DRE refers to
                                a captured variable, because that is not
                                a local property of the DRE; it depends
                                on non-trivial properties of the context
                                in which the DRE is used (and more
                                generally it depends on how else that
                                same variable is used elsewhere in the
                                lambda, but we can largely ignore that).<br
                                  class="">
                                >><br class="">
                                >> I'd be fine having separate
                                flags for 'refers to enclosing local'
                                and 'refers to captured global' (if the
                                latter is the point of this change), but
                                we should not claim a DRE refers to a
                                capture when it does not.<br class="">
                                ><br class="">
                                ><br class="">
                                > Richard, I understand that not all
                                DREs are potentially evaluated and thus
                                may not actually induce capturing, and I
                                concede your point that the flag's name
                                shouldn’t use the word “capture” if it’s
                                set on unevaluated DREs.  The question
                                is this: what information do we actually
                                need to track on DREs?<br class="">
                                ><br class="">
                                > It is very useful for IR-gen to be
                                able to immediately know whether a DRE
                                refers to a captured local or global
                                variable, no matter why that capture was
                                performed.  As far as I’m aware, IR-gen
                                does not care about whether the flag is
                                set on unevaluated references to
                                enclosing variables, because IR-gen
                                should never see an unevaluated use in
                                normal expression emission.</p>
                              <p dir="ltr" class="">This is not about
                                unevaluated references, it's about
                                evaluated references that aren't odr
                                uses, which depends on the context in
                                which the DRE appears. IRGen does need
                                to deal with these cases.</p>
                            </div>
                          </blockquote>
                        </span>Ugh, fine, I will go haul out the
                        standard to figure out what you’re talking
                        about, since you are apparently in a vague mood
                        tonight.</div>
                    </div>
                  </blockquote>
                  <div class=""><br class="">
                  </div>
                  <div class="">Apologies for the terseness, was
                    replying from a phone.</div>
                  <div class=""> </div>
                  <blockquote class="gmail_quote" style="margin:0px 0px
                    0px
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
                    <div style="word-wrap:break-word" class="">
                      <div class="">Okay, I believe what you’re saying
                        is:</div>
                      <div class="">1. A reference to an entity (a
                        variable/this) within a lambda only causes a
                        capture if it's an ODR use.</div>
                      <div class="">2. All ODR uses are PE references,
                        but a PE reference isn't an ODR use if the
                        variable can be used in a constant expression
                        and it's a potential result of an expression
                        that’s either ignored or loaded.</div>
                      <div class="">3. Whether an expression is ignored
                        or loaded cannot be decided immediately from
                        context; you have to semantically process the
                        entire expression, and it may be different in
                        different template instantiations.  (This
                        dependence is also true of PPE-ness, I think.)</div>
                      <div class="">4. Since we sometimes share DRE
                        nodes, we can’t retroactively alter a node after
                        doing the necessary semantic analysis.</div>
                      <div class="">5. AST clients are likely to want to
                        know whether a DRE is not an ODR-use and can
                        only be constant-evaluated.  For example, it’s
                        important that IR-gen not actually emit a
                        reference to a static member variable of a class
                        template if that member variable hasn’t been
                        ODR-used.  Clients should similarly not be
                        confused by an evaluated reference to an
                        uncaptured enclosing local.</div>
                      <div class=""><br class="">
                      </div>
                      <div class="">I think point #4 tells us that the
                        desired information in #5 can’t actually be
                        directly represented in the AST, though.</div>
                    </div>
                  </blockquote>
                  <div class=""><br class="">
                  </div>
                  <div class="">Yes, that's an excellent summary. For
                    concreteness, here's an example where this happens:</div>
                  <div class="">
                    <pre style="" class="">void f(int, int);
void f(const int&, double);
auto f() {
  const int n = 0;
  return [=](auto t) { return [=]() { f(n, t); } };
}
void g() { f()(0)(); f()(0.)(); }</pre>
                  </div>
                  <div class="">Here, the lambda returned by f()(0) does
                    not capture 'n', but the lambda returned by f()(0.)
                    does, and they share a DeclRefExpr for n.<br
                      class="">
                  </div>
                  <div class=""><br class="">
                  </div>
                  <blockquote class="gmail_quote" style="margin:0px 0px
                    0px
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
                    <div style="word-wrap:break-word" class="">
                      <div class="">But as the first example shows,
                        client interests in #5 are much broader than
                        just references to enclosing locals.  IR-gen
                        would benefit from knowing whether an arbitrary
                        expression was constant-evaluable; currently it
                        has hacky code to try to constant-evaluate
                        specific nodes, and it lets all the other nodes
                        fall out from LLVM’s own constant-folding and
                        optimization, but it would clearly be better to,
                        say, know that a particular call is a call to a
                        constexpr function with constant arguments and
                        so we can just directly try to fold it instead
                        of emitting a whole bunch of unnecessary code
                        that will get cleaned up later.  Using “this is
                        an enclosing local” as an incomplete
                        approximation of that isn’t actually useful.</div>
                    </div>
                  </blockquote>
                  <div class=""><br class="">
                  </div>
                  <div class="">The only cases where we need to emit
                    different code based on whether an expression is a
                    constant expression (outside unevaluated contexts)
                    are when initializing a variable of
                    static/thread_local storage duration, and when an
                    expression refers to an enclosing local variable
                    that it doesn't capture.</div>
                </div>
              </div>
            </div>
          </div>
        </blockquote>
        <div><br class="">
        </div>
        <div>You’re forgetting references to static data members, which
          don’t have to be defined if they have a constant initializer
          in the class definition and are never ODR-used.  (Of course,
          in practice people learn to avoid writing code that relies on
          this because it’s too easy to accidentally ODR-use a variable;
          but it’s in the spec.)  This is something that can’t as easily
          be hacked around in IRGen.</div>
        <br class="">
        <blockquote type="cite" class="">
          <div class="">
            <div dir="ltr" class="">
              <div class="gmail_extra">
                <div class="gmail_quote">
                  <div class=""> In all other cases, it's correct and
                    often reasonable to evaluate the expression at
                    runtime.</div>
                </div>
              </div>
            </div>
          </div>
        </blockquote>
        <div><br class="">
        </div>
        <div>It’s correct, but it’s easy to imagine code where this
          causes a great deal of unnecessary code to be emitted,
          optimized, and finally thrown away.</div>
        <div><br class="">
        </div>
        <div>Also we probably have bugs involving some of the recursive
          cases of potential results where IRGen will introduce illegal
          symbol references.  I’m particularly concerned about loads
          from members.</div>
        <br class="">
        <blockquote type="cite" class="">
          <div class="">
            <div dir="ltr" class="">
              <div class="gmail_extra">
                <div class="gmail_quote">
                  <div class="">In the case where a lambda expression
                    refers to an enclosing local but doesn't capture it,
                    we should emit a copy of that local's value as a
                    constant global.</div>
                </div>
              </div>
            </div>
          </div>
        </blockquote>
        <div><br class="">
        </div>
        Sure.<br class="">
        <div><br class="">
        </div>
        <blockquote type="cite" class="">
          <div class="">
            <div dir="ltr" class="">
              <div class="gmail_extra">
                <div class="gmail_quote">
                  <blockquote class="gmail_quote" style="margin:0px 0px
                    0px
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
                    <div style="word-wrap:break-word" class="">
                      <div class="">So it seems to me that we just need
                        one bit, called
                        refersToEnclosingVariableOrCapture(), with the
                        meaning that it’s set if the DRE refers to an
                        enclosing local (captured or not) or captured
                        global variable, regardless of whether this
                        reference is an ODR use.</div>
                    </div>
                  </blockquote>
                  <div class=""><br class="">
                  </div>
                  <div class="">That seems fine to me.</div>
                </div>
              </div>
            </div>
          </div>
        </blockquote>
      </div>
      <br class="">
      <div class="">Okay.  Alexey, would you mind doing this after you
        get back from break?</div>
      <div class=""><br class="">
      </div>
      <div class="">John.</div>
    </blockquote>
    <br>
  </body>
</html>