<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 29, 2013 at 5:01 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="im">On Wed, May 29, 2013 at 11:19 AM, Faisal Vali <span dir="ltr"><<a href="mailto:faisalv@gmail.com" target="_blank">faisalv@gmail.com</a>></span> wrote:<br>
</div></blockquote><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><div>I assume you didn't mean to include the changes to ParseAST.cpp?</div>
<div class="im"><div> </div></div></div></blockquote><div><br>No I did not. Sorry - I'll try and be better about that - but it might happen again ;)<br><br></div><div class="im"> <div><br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote"><div><div>Index: include/clang/Sema/Sema.h</div><div>===================================================================</div>
<div>--- include/clang/Sema/Sema.h<span style="white-space:pre-wrap">     </span>(revision 182855)</div><div>+++ include/clang/Sema/Sema.h<span style="white-space:pre-wrap">   </span>(working copy)</div>
<div>@@ -3016,6 +3016,9 @@</div><div>   void MarkMemberReferenced(MemberExpr *E);</div><div> </div><div>   void UpdateMarkingForLValueToRValue(Expr *E);</div><div>+  // Assess the expression for any references to a variable</div>

<div>+  // that do not entail an odr-use of that variable.</div><div>+  void UpdateNonODRUsedVariableReferences(Expr *E);</div></div><div><br></div><div>Isn't this function the same thing as UpdateMarkingForLValueToRValue? Maybe merge them into a single function? (FWIW, I prefer the old name.)</div>

<div><br></div></div></blockquote><div>Done.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><div></div>
<div><br></div><div><div>@@ -11508,13 +11508,23 @@</div><div>   // Note that we use the C++11 definition everywhere because nothing in</div><div>   // C++03 depends on whether we get the C++03 version correct. The second</div>

<div>   // part does not apply to references, since they are not objects.</div><div>+  // Per DR: 712 constant expressions in discarded value expressions</div><div>+  // are not odr-used either.</div><div><br></div><div>
The mention of discarded value expressions seems out of place here.</div>
<div><br></div><div>+  // <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3383.html#712" target="_blank">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3383.html#712</a></div><div><br></div><div>
We usually don't include such links in comments.</div>
<div><br></div><div>+  // </div><div>   const VarDecl *DefVD;</div><div>-  if (E && !isa<ParmVarDecl>(Var) &&</div><div>+  if (E && SemaRef.getLangOpts().CPlusPlus11 && </div><div>+                  E->isCXX11ConstantExpr(SemaRef.Context)) {</div>

<div>+    if (!Var->getType()->isReferenceType())</div><div>+      SemaRef.MaybeODRUseExprs.insert(E);</div><div><br></div><div>Hah, this is a literal interpretation of the standard text, but isn't what was intended. It allows DeclRefExprs referring to globals, for instance. What was *intended* was to look for objects on which the lvalue-to-rvalue conversion could be applied in a constant expression, that is, what the existing code does:</div>

<div> </div></div></div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><div><div></div><div>+  }</div><div>+  else if (E && !isa<ParmVarDecl>(Var) &&</div>
</div><div><div>       Var->isUsableInConstantExpressions(SemaRef.Context) &&</div><div>       Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) {</div>
</div><div><br></div></div></blockquote><div>Done.  The comment might need some additional work though. <br></div><div><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote"><div></div><div><br></div><div><div>Index: lib/Sema/SemaExprCXX.cpp</div><div>===================================================================</div><div>--- lib/Sema/SemaExprCXX.cpp<span style="white-space:pre-wrap">  </span>(revision 182855)</div>

<div>+++ lib/Sema/SemaExprCXX.cpp<span style="white-space:pre-wrap">      </span>(working copy)</div><div>@@ -5518,6 +5518,78 @@</div><div>   return false;</div><div> }</div><div> </div><div>+namespace {</div>
<div>+  </div><div>+  struct ConstantExpressionODRCleaner : RecursiveASTVisitor<</div><div>+                                 ConstantExpressionODRCleaner> {</div><div>+</div></div><div><br></div><div>We normally don't include blank lines in these cases. Also, maybe split this line after the : instead of after the < ?</div>

<div><br></div></div></blockquote><div>Done.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><div></div>
<div>A RecursiveASTVisitor seems overkill here, since you're neither using the recursive walk, nor dispatch on anything other than Stmts. Maybe this should be a ConstStmtVisitor instead?</div><div><div>
<div><br></div></div></div></div></blockquote><div>Done.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote">
<div><div><div></div><div>Maybe name this something like PotentialResultsSetFinder, since that's closer to what it does.</div><div><br></div></div></div></div></blockquote><div>Done. <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote"><div><div><div></div><div><br></div><div>+    llvm::SmallPtrSet<Expr*, 2>& MaybeODRUseExprs;</div>
</div><div><br></div><div>" &", not "& ", please. I have other formatting-related comments on this patch, but clang-format can tell you what they are. :-)</div><div><br></div></div></div></blockquote>
<div> </div><div>Once I obtain your feedback on this revision - and prior to my next revision, i'll try and figure out how to use clang-format - thanks!<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote"><div><div></div><div><br></div><div>
+    typedef RecursiveASTVisitor<ConstantExpressionODRCleaner> inherited;</div></div><div><br></div><div>Should be "Inherited", bu just remove this since you're not actually using it.</div><div><br></div>

<div><br></div><div><div>+    // C++14 CD, DR 712: 3.2 para 2</div></div><div><br></div><div>Please use "C++1y" here so that we can more easily find it with a grep later.</div><div><br></div></div></blockquote>
<div>Done.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><div></div><div><br></div><div>
<div>+    // normally, we don't need to do any additional conversions to handle it, </div></div><div><div>+    // but if it is a volatile lvalue with a special form, we perform an </div><div>+    // lvalue-to-rvalue conversion.  Additionally, if it was a c++11 constant</div>

<div>+    // expression.</div></div><div><br></div><div>The added comment here doesn't look right; I think you should say something like "Even if we do not perform an lvalue-to-rvalue conversion, we pretend that one was performed when checking for odr-uses of variables."</div>

<div><br></div><div><br></div></div></blockquote><div>Done.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote">
<div></div><div><div>Index: lib/CodeGen/CGExpr.cpp</div><div>===================================================================</div><div><br></div><div>You have CodeGen changes but no tests for them, please add some, covering all the ways in which a variable can be referenced without being odr-used.</div>

<div><br></div></div></div></blockquote><div><br></div><div>Still no codegen tests on this revision - will include them with my next revision once i get your technical feedback on this one (and figure out the LLVM IR i need to<br>
ramp up on, so that I can start writing codegen tests for this).  Any preliminary guidance will be appreciated.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote"><div><div></div><div><br></div><div>--- lib/CodeGen/CGExpr.cpp<span style="white-space:pre-wrap">    </span>(revision 182855)</div><div>+++ lib/CodeGen/CGExpr.cpp<span style="white-space:pre-wrap">      </span>(working copy)</div>

<div>@@ -1800,6 +1800,13 @@</div><div>   return CGF.EmitLValueForField(LV, FD);</div><div> }</div><div> </div><div>+</div><div>+inline bool isLambdaCallOperator(const Decl *D) {</div></div><div><br></div><div>This seems generally useful; perhaps it should be a member of CXXMethodDecl? If not, s/inline/static/, please.</div>

<div><br></div></div></blockquote><div>This still needs to be done.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote">
<div></div><div><br></div><div><div>+  if (!ND->isUsed(false) || (E->refersToEnclosingLocal() && </div><div>+                              isLambdaCallOperator(CurCodeDecl))) {</div><div>+    if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {</div>

</div><div><br></div><div>Please flip these two 'if's around, and merge this into the preceding code (the end result should just be removing the isReferenceType() check from the preceding code block and adding the lambda-enclosing-local check).</div>

<div><br></div><div><br></div></div></blockquote><div>Done.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote">
<div></div><div><div><div>@@ -2476,7 +2497,23 @@</div><div> </div><div> LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {</div><div>   Expr *BaseExpr = E->getBase();</div><div>+  ASTContext &Context = CGM.getContext();</div>

<div>+  APValue ConstExprResult;</div><div> </div><div>+  // Emit a field member access that evaluates to a constexpr s.x </div><div>+  if (Context.getLangOpts().CPlusPlus11 && E->isCXX11ConstantExpr(Context, </div>

<div>+          &ConstExprResult)) {</div><div>+    if (FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) {</div><div>+      CharUnits Alignment = Context.getDeclAlign(FD);</div><div>+      llvm::Constant *Val =</div>

<div>+        CGM.EmitConstantValue(ConstExprResult, FD->getType(), this);</div><div>+      assert(Val && "failed to emit C++11 constant member expression");</div><div>+      // FIXME: Eventually we will want to emit vector element references.</div>

<div>+      QualType T = E->getType();</div><div>+      return MakeAddrLValue(Val, T, Alignment);</div><div>+    }</div><div>+  }</div><div></div></div></div><div><br></div><div>I don't think this approach can work. Consider this:</div>

<div><br></div><div>  struct S { int x; };</div><div>  constexpr S a = { 1 };</div><div>  S b = { 2 };</div><div>  bool k;</div><div>  return (k ? a : b).x;</div><div><br></div><div>This does not odr-use 'a', but it does odr-use 'b'. The MemberExpr is not a constant expression here. I think instead what you should do is to teach AggExprEmitter (and friends) to directly emit a constant value when they visit a DeclRefExpr which is not an odr-use</div>

<div><br></div></div></blockquote><div><br></div><div>I think I fixed this - but I must admit I was unable to figure out how to fix it through AggExprEmitter.  My fix uses a visitor in CodeGenFunction::EmitDeclRefExpr<br>
</div><div>to try and figure out whether the DeclRefExpr is in a conditional operator context of an object expression of a member expression (which is pushed onto a stack), and if <br></div><div>that is the case, it emits a pointer to the struct vs the constant version of the struct.  It seems to pass my tests - but like i said earlier, I have not had the time yet<br>
to write the appropriate LLVM-IR codegen tests.  Please let me know about the robustness of my fix - it does feel a little brittle to me.  If you stiill feel<br></div><div>AggExprEmitter is the way to go with this, I could certainly use a little guidance as to how we enter into AggExprEmitter while emitting code for the conditional expr.<br>
</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><div></div><div><br></div><div><div>@@ -3239,6 +3276,23 @@</div>
<div> LValue CodeGenFunction::</div><div> EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {</div><div>   llvm::Value *BaseV;</div><div>+  </div>
<div>+  Expr *ObjExpr = E->getLHS();</div><div>+  ASTContext &Context = CGM.getContext();</div><div>+  APValue ConstExprResult;</div><div>+  // Emit a field member access that evaluates to a constexpr s.*memfn </div>

<div>+  if (Context.getLangOpts().CPlusPlus11 && E->isCXX11ConstantExpr(Context, </div><div>+        &ConstExprResult)) {</div><div>+    const MemberPointerType *MPT</div><div>+                  = E->getRHS()->getType()->getAs<MemberPointerType>();</div>

<div>+    llvm::Constant *Val =</div><div>+      CGM.EmitConstantValue(ConstExprResult, MPT->getPointeeType(), this);</div><div>+    assert(Val && "failed to emit C++11 constant member expression");</div>

<div>+    // FIXME: Eventually we will want to emit vector element references.</div><div>+    QualType T = E->getType();</div><div>+    return MakeAddrLValue(Val, T);</div><div>+  }</div></div><div><br></div><div>In this case, you should constant-evaluate the RHS but not the LHS. Also, use EvaluateAsRValue here; it doesn't matter whether we need to perform non-standard constant folding. And there's no need to check for C++11 mode.</div>

<div><br></div><div><br></div></div></blockquote><div>Done.<br><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote">
<div></div><div><div>Index: test/CXX/basic/basic.def.odr/p2-DR712-C++14-CD.cpp</div><div>===================================================================</div><div>--- test/CXX/basic/basic.def.odr/p2-DR712-C++14-CD.cpp<span style="white-space:pre-wrap">        </span>(revision 0)</div>

<div>+++ test/CXX/basic/basic.def.odr/p2-DR712-C++14-CD.cpp<span style="white-space:pre-wrap">    </span>(working copy)</div></div><div><br></div><div>Maybe just call this .../p2-potential-results.cpp -- this isn't C++1y-specific. This file contains both UTF-8 characters in comments and \r\n line separators, please fix.</div>
<div><div class="h5">
<div></div></div></div></div></blockquote><div><br></div><div>Done.<br><br><br></div><div>Await your feedback ...<br><br></div><div>Also *ping* the patch (<a href="http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130506/079656.html" target="_blank">http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130506/079656.html</a>) was LGTM'd by Doug, anyway we can get that one committed please - thank you!<br>


</div><div><br></div><div>Thanks again Richard!<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><div>
<div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div><div><div class="gmail_extra"></div><div class="gmail_extra">
<br><br><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, May 18, 2013 at 1:42 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>On Sat, May 18, 2013 at 9:22 AM, Faisal Vali <span dir="ltr"><<a href="mailto:faisalv@gmail.com" target="_blank">faisalv@gmail.com</a>></span> wrote:<br>


</div><div class="gmail_quote"><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr">Before I return to working on generic lambdas, I thought it might be useful to nail down DR 712 which reworded the definition of odr-use in terms of the potential results of an expression (in order to avoid odr-using a variable that represents a constant expression whenever we can get away with it).  This is relevant to lambdas, because it affects which variables get captured and which don't.<br>




<br><br><div><div><div class="gmail_extra">Let me review how I think clang currently handles this (pre-712 resolution  - please correct me where I err). While parsing and semanalyzing expressions, all variables that are usable in constant expressions (and so might not need to be odr-used) are stored in MaybeODRUseExprs (a set container) as DeclRefExprs (DRE).  Then, if an Lvalue-to-Rvalue conversion is performed on the DRE, it is removed from the set above (In UpdateMarkingForLValueToRValue).  Anything left in that set is marked as odr-used by ActOnFinishFullExpr.  <br>




<br><br></div><div class="gmail_extra">OK, with the above in mind, these are my initial thoughts on how to implement it so that not only do we handle those constant expressions that are lvalue-to-rvalue converted, but also those that are discarded, and also handle the conditional expressions and member-access expressions.<br>




<br></div><div class="gmail_extra">The relevant hooks/callbacks/functions within clang are:<br></div><div class="gmail_extra">  - UpdateMarkingForLValueToRValue<br></div><div class="gmail_extra">  - IgnoredValueConversions<br>




<br></div><div class="gmail_extra">A function i intend to write is GetPotentialResultsOfExpression: when passed an Expr* E, returns a vector of its potential results as DeclRefExpr's (and MemberExpr's??); this function should follow from  3.2 para 2.<br>




<br>Now in each hook, GetPotentialResults shall be called, and those expressions shall be removed from the MaybeODRUseExpr.<br></div></div></div></div></blockquote><div><br></div></div><div>This seems like the right approach, although you presumably don't actually need to build the vector and could just remove the odr-use marker directly.</div>


<div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div class="gmail_extra"></div><div class="gmail_extra">What are your thoughts on the above preliminary strategy?  I have this sense that Member expressions are going to require some more work, but we'll see...<br>




</div><div class="gmail_extra"><br></div><div class="gmail_extra">Also before I proceed any further, I was hoping to get some more clarity on 3.2 para 2 and para 3 - please see my queries below:<br><br><br><div class="gmail_extra">




Consider the following code:<br><br><br>struct S {<br>  const int mi;<br>  constexpr S(int i) : mi(i) { }<br>};<br><br></div><div class="gmail_extra">int f(const int& );<br>void g(int);<br>int main() {<br>  constexpr S r{5};<br>




  constexpr S s{r};<br>  [](char c) {  <br>      c = s.mi;  // #1 does this odr-use 's'<br></div></div></div></div></div></blockquote><div><br></div></div><div>No. Here, e = 's.mi', ex = 's' (a member of the set of potential results of e), and e is subject to an lvalue-to-rvalue conversion.</div>


<div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div class="gmail_extra"><div class="gmail_extra"></div><div class="gmail_extra">


      g(s.mi);   //  #2 what about this?<br>
</div></div></div></div></div></blockquote><div><br></div></div><div>Also no, because an lvalue-to-rvalue conversion is applied to s.mi.</div><div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">



<div dir="ltr"><div><div><div class="gmail_extra"><div class="gmail_extra"></div><div class="gmail_extra">      s.mi;        // #3 and this?<br></div></div></div></div></div></blockquote><div><br></div></div><div>Also no, because this is a discarded-value expression.</div>


<div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div class="gmail_extra"><div class="gmail_extra">
</div><div class="gmail_extra">      c ? s.mi : r.mi; // #4 and this?<br></div></div></div></div></div></blockquote><div><br></div></div><div>Also no.</div><div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">



<div dir="ltr"><div><div><div class="gmail_extra"><div class="gmail_extra"></div><div class="gmail_extra">      g( c ? s.mi : r.mi ); // #5<br></div></div></div></div></div></blockquote><div><br></div></div><div>Also no.</div>


<div><div>
 </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div class="gmail_extra"><div class="gmail_extra"></div><div class="gmail_extra">


  };<br>
}<br></div><br></div><div class="gmail_extra">
My intial suspicion was that neither s nor r were odr-used in the lambda (because the compiler can figure out the value of 'mi' at its point of use, and use it or discard it) - but then based on Richard's analysis of the example below where he states that s.operator int() is an odr-use of 's', i am now unsure.<br>



</div></div></div></div></blockquote><div><br></div></div><div>Note that member function calls aren't listed in the rules of 3.2/2. 's' is not in the set of potential results of 's.operator int()'.</div>


<div><div>
 </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div class="gmail_extra">Here is my attempt at trying to figure this out (e refers to expression, ex as a potentially-evaluated expression, using the language of 3.2 para 2 and 3)<br>



<br></div><div class="gmail_extra">In #1, <br></div><div class="gmail_extra">
  the variable 's' appears as a potentially evaluated expression and satisfies the requirements for appearing in a constant expression, and it is an object, and it is an element of the set of potential results of an expression 'e' (s.mi) and the lvalue-to-rvalue conversion is applied to that expression so it is not odr-used?  But what if 'e' is deemed to be 's' in 's.mi' - no lvalue-to-rvalue conversion is applied so it should be captured?<br>



</div></div></div></div></blockquote><div><br></div></div><div>The rule says: "x [...] is odr-used unless [...] ex is is an element of the set of potential results of an expression e, where [...]"</div><div><br>


</div>
<div>That is, if there *exists* such an 'e', then 'x' is not odr-used.</div><div><br></div><div>Hope that helps!</div><div><div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">



<div dir="ltr"><div><div><div class="gmail_extra"></div><div class="gmail_extra">OK, I'm going to give up on analyzing the rest, because I feel I'm missing something and am unable to think about this clearly.<br>


<br>
</div><div class="gmail_extra">Any help or guidance will be appreciated!<br>
<br> </div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 15, 2013 at 3:21 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br>




<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div>On Tue, May 14, 2013 at 9:48 PM, Faisal Vali <span dir="ltr"><<a href="mailto:faisalv@gmail.com" target="_blank">faisalv@gmail.com</a>></span> wrote:<br>




</div></div><div class="gmail_quote"><div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div dir="ltr"><br><div class="gmail_quote"><br><div>While we're on the topic, can i ask you to clarify a few capture and constexpr <br>questions below:<br></div></div></div></blockquote></div></div><div><div>
<div><br></div></div></div><div>OK, the relevant context is [basic.def.odr]p2 and p3.</div><div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div>struct S {</div>




<div>  constexpr S() {}</div>
<div>  constexpr operator int() const { return 0; }<br>
</div><div>};<br></div><div>void fooS(S s) { }<br></div><div><br>void fooInt(int i) { }<br><br></div><div><div>void f() {</div><div>  constexpr S s {};</div></div><div>  auto L = [] (int x) {</div>      (void) s;  // 1<br>





</div></div></div></div></blockquote><div><br></div></div><div>Here, the 's' expression is a discarded-value expression, and the 's' variable is in the set of potential results of the 's' expression, and 's' satisfies the constraints for appearing in a constant expression, so 's' is not odr-used, so is not captured. We should not require a capture-default here.</div>





<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div>
      fooS(s);  // 2<br></div></div></div></div></blockquote><div><br></div><div>Here, 's' is implicitly passed to the implicit S::S(const S&) constructor. This is neither an lvalue-to-rvalue conversion nor a discarded-value expression, so 's' is odr-used and we have an error due to the missing capture-default.</div>





<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div>      fooInt(s); // 3<br>




</div>
</div></div></div></blockquote><div><br></div><div>This is equivalent to 's.operator int()', which again odr-uses 's', so requires a capture-default.</div><div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">





<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div><div>  };<br></div><div>}<br><br></div><div>Should the above be ok in spite of L not having a default capture?<br></div>Currently clang errors on all of them individually - is that the right behavior?<br>






<br>Also, how would you want me to start submitting patches for commit - do you want <br>me to break up the patch into smaller patches? - and if so, do you have any thoughts <br>on how I might want to break up the functionality per patch?</div>





</div></div></div></blockquote><div><br></div></div><div>Smaller patches are definitely better, if you can decompose the functionality into coherent smaller chunks. There are some hints on how to decompose the functionality here (but this division may or may not work for you):</div>





<div><br></div><div><a href="http://clang.llvm.org/docs/InternalsManual.html#how-to-add-an-expression-or-statement" target="_blank">http://clang.llvm.org/docs/InternalsManual.html#how-to-add-an-expression-or-statement</a></div>




</div>
</blockquote></div><br></div></div></div></div>
</blockquote></div></div></div><br>
</blockquote></div><br></div></div></div></div></div></div>
</blockquote></div></div></div><br>
</blockquote></div><br></div></div>