<div dir="ltr"><br><div class="gmail_extra"><div class="gmail_quote">On Fri, Jun 7, 2013 at 5: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 class="im">On Tue, Jun 4, 2013 at 9:19 PM, Faisal Vali <<a href="mailto:faisalv@gmail.com">faisalv@gmail.com</a>> wrote:<br>

> OK - this patch adds the following:<br>
>  0) Some codegen tests, and additional non-codegen tests.<br>
>  1) If the pointer to member expression can be entirely folded into a<br>
> constant, do so.<br>
>  2) If the object expression in a member access (be it through dot, or<br>
> pointer to member) is a constant<br>
>      but the containing expression could not be folded into a constant - do<br>
> not emit the object as a constant<br>
>      - instead get the variable's address using getStaticLocalDeclAddress<br>
> (it appears that constants are<br>
>        hoisted out as globals in llvm IR) so that getelementptr has a<br>
> pointer to work with.<br>
><br>
> Am patiently awaiting feedback - because if i am on the right track, hoping<br>
> i can get this committed soon; if I am way off, I would like to walk away<br>
> from this, so that I can return to working on generic lambdas ;)<br>
<br>
</div>The Sema part looks good.<br>
<br></blockquote><div>OK.  No changes made to that portion, in this patch.  <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">

For the CodeGen part, I think you should approach the problem somewhat<br>
differently. CodeGen emits expressions as RValues or LValues based on<br>
how they are used, not based on whether the expressions themselves are<br>
rvalues or lvalues, and in particular, an operand of an<br>
lvalue-to-rvalue conversion is typically emitted directly as an<br>
rvalue. So if you ensure that RValue emission never actually performs<br>
a load in the cases which are not odr-uses, then you should be OK.<br>
 </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
One problem is that, in some cases, the rvalue emission defers to<br>
lvalue emission; emitting pointer-to-member access is one of those<br>
cases. I think what you should do here is to teach the<br>
ScalarExprEmitter to try to evaluate the right-hand side of the<br>
pointer-to-member expression, and emit a direct field access if it<br>
can.<br>
<div class=""><div class="h5"><br></div></div></blockquote><div><br><div>As per your suggestions, I have reworked the codegen portion as following:<br></div><div>  1) CGF::EmitIgnoredExpr checks to see if it is a constant expression, and then <br>
</div><div>      defers to RValue Emission (at least i think my change does that, am I correct?)<br></div><div>  2) CGF::EmitDeclRef now handles unused variables that are constant expressions <br></div><div>      as long as they are mentioned within lambdas or found within the local decl map.<br>
</div><div>  3) I taught both AggExprEmitter::VisitPointerToDataMember and AEE::VisitMemberExpr<br></div><div>     to emit constant values as Rvalues (I am not sure about the volatile qualifier) - but<br></div><div>     this is what I think you had initially suggested.<br>
</div><div>  4) I taught the ScalarExprEmitter::VisitMemberExpr and VisitBinPtr to emit<br></div><div>      constant values.  Do I need to call EmitConstantValue in <br></div><div>      VisitMemberExpr - it does not seem to generate code?  Also I think I've implemented<br>
      what you were suggesting - that is if the pointer-to-mem can be evaluated as an RValue,<br>      then emitting the field decl directly.  Am I correct in assuming that this only needs<br></div><div>      to deal with member pointers that are field-decls? (ignore functions and vardecls?!). I have<br>
</div><div>      included commented out code for non-field decls, can i erase this?        <br></div><div> <br>Is this closer to what you had in mind?<br></div></div><div><br></div><div>Also do you have any thoughts on using clang-format in windows so that it won't<br>
</div><div>screw up the new lines?<br></div><div><br></div><div>Thanks Richard!<br> <br></div><div>-fas<br><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=""><div class="h5">
> On Mon, Jun 3, 2013 at 2:54 PM, Faisal Vali <<a href="mailto:faisalv@gmail.com">faisalv@gmail.com</a>> wrote:<br>
>><br>
>> An updated patch that fixes emission of pointers to members.<br>
>><br>
>> Codegen tests and clang-format is still pending feedback regarding the<br>
>> strategy i used to fix the member access issue.<br>
>> Thank you!<br>
>><br>
>> Faisal Vali<br>
>><br>
>><br>
>><br>
>> On Sun, Jun 2, 2013 at 2:36 PM, Faisal Vali <<a href="mailto:faisalv@gmail.com">faisalv@gmail.com</a>> wrote:<br>
>>><br>
>>><br>
>>><br>
>>> On Wed, May 29, 2013 at 5:01 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>><br>
>>> wrote:<br>
>>>><br>
>>>> On Wed, May 29, 2013 at 11:19 AM, Faisal Vali <<a href="mailto:faisalv@gmail.com">faisalv@gmail.com</a>> wrote:<br>
>>><br>
>>><br>
>>>> I assume you didn't mean to include the changes to ParseAST.cpp?<br>
>>>><br>
>>><br>
>>><br>
>>> No I did not. Sorry - I'll try and be better about that - but it might<br>
>>> happen again ;)<br>
>>><br>
>>><br>
>>><br>
>>>> Index: include/clang/Sema/Sema.h<br>
>>>> ===================================================================<br>
>>>> --- include/clang/Sema/Sema.h (revision 182855)<br>
>>>> +++ include/clang/Sema/Sema.h (working copy)<br>
>>>> @@ -3016,6 +3016,9 @@<br>
>>>>    void MarkMemberReferenced(MemberExpr *E);<br>
>>>><br>
>>>>    void UpdateMarkingForLValueToRValue(Expr *E);<br>
>>>> +  // Assess the expression for any references to a variable<br>
>>>> +  // that do not entail an odr-use of that variable.<br>
>>>> +  void UpdateNonODRUsedVariableReferences(Expr *E);<br>
>>>><br>
>>>> Isn't this function the same thing as UpdateMarkingForLValueToRValue?<br>
>>>> Maybe merge them into a single function? (FWIW, I prefer the old name.)<br>
>>>><br>
>>> Done.<br>
>>><br>
>>>><br>
>>>><br>
>>>> @@ -11508,13 +11508,23 @@<br>
>>>>    // Note that we use the C++11 definition everywhere because nothing<br>
>>>> in<br>
>>>>    // C++03 depends on whether we get the C++03 version correct. The<br>
>>>> second<br>
>>>>    // part does not apply to references, since they are not objects.<br>
>>>> +  // Per DR: 712 constant expressions in discarded value expressions<br>
>>>> +  // are not odr-used either.<br>
>>>><br>
>>>> The mention of discarded value expressions seems out of place here.<br>
>>>><br>
>>>> +  //<br>
>>>> <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><br>
>>>><br>
>>>> We usually don't include such links in comments.<br>
>>>><br>
>>>> +  //<br>
>>>>    const VarDecl *DefVD;<br>
>>>> -  if (E && !isa<ParmVarDecl>(Var) &&<br>
>>>> +  if (E && SemaRef.getLangOpts().CPlusPlus11 &&<br>
>>>> +                  E->isCXX11ConstantExpr(SemaRef.Context)) {<br>
>>>> +    if (!Var->getType()->isReferenceType())<br>
>>>> +      SemaRef.MaybeODRUseExprs.insert(E);<br>
>>>><br>
>>>> Hah, this is a literal interpretation of the standard text, but isn't<br>
>>>> what was intended. It allows DeclRefExprs referring to globals, for<br>
>>>> instance. What was *intended* was to look for objects on which the<br>
>>>> lvalue-to-rvalue conversion could be applied in a constant expression, that<br>
>>>> is, what the existing code does:<br>
>>>><br>
>>>><br>
>>>> +  }<br>
>>>> +  else if (E && !isa<ParmVarDecl>(Var) &&<br>
>>>>        Var->isUsableInConstantExpressions(SemaRef.Context) &&<br>
>>>>        Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) {<br>
>>>><br>
>>> Done.  The comment might need some additional work though.<br>
>>><br>
>>><br>
>>>><br>
>>>><br>
>>>> Index: lib/Sema/SemaExprCXX.cpp<br>
>>>> ===================================================================<br>
>>>> --- lib/Sema/SemaExprCXX.cpp (revision 182855)<br>
>>>> +++ lib/Sema/SemaExprCXX.cpp (working copy)<br>
>>>> @@ -5518,6 +5518,78 @@<br>
>>>>    return false;<br>
>>>>  }<br>
>>>><br>
>>>> +namespace {<br>
>>>> +<br>
>>>> +  struct ConstantExpressionODRCleaner : RecursiveASTVisitor<<br>
>>>> +                                 ConstantExpressionODRCleaner> {<br>
>>>> +<br>
>>>><br>
>>>> We normally don't include blank lines in these cases. Also, maybe split<br>
>>>> this line after the : instead of after the < ?<br>
>>>><br>
>>> Done.<br>
>>><br>
>>>><br>
>>>> A RecursiveASTVisitor seems overkill here, since you're neither using<br>
>>>> the recursive walk, nor dispatch on anything other than Stmts. Maybe this<br>
>>>> should be a ConstStmtVisitor instead?<br>
>>>><br>
>>> Done.<br>
>>><br>
>>>><br>
>>>> Maybe name this something like PotentialResultsSetFinder, since that's<br>
>>>> closer to what it does.<br>
>>>><br>
>>> Done.<br>
>>>><br>
>>>><br>
>>>> +    llvm::SmallPtrSet<Expr*, 2>& MaybeODRUseExprs;<br>
>>>><br>
>>>> " &", not "& ", please. I have other formatting-related comments on this<br>
>>>> patch, but clang-format can tell you what they are. :-)<br>
>>>><br>
>>><br>
>>> Once I obtain your feedback on this revision - and prior to my next<br>
>>> revision, i'll try and figure out how to use clang-format - thanks!<br>
>>><br>
>>>><br>
>>>><br>
>>>> +    typedef RecursiveASTVisitor<ConstantExpressionODRCleaner><br>
>>>> inherited;<br>
>>>><br>
>>>> Should be "Inherited", bu just remove this since you're not actually<br>
>>>> using it.<br>
>>>><br>
>>>><br>
>>>> +    // C++14 CD, DR 712: 3.2 para 2<br>
>>>><br>
>>>> Please use "C++1y" here so that we can more easily find it with a grep<br>
>>>> later.<br>
>>>><br>
>>> Done.<br>
>>><br>
>>>><br>
>>>><br>
>>>> +    // normally, we don't need to do any additional conversions to<br>
>>>> handle it,<br>
>>>> +    // but if it is a volatile lvalue with a special form, we perform<br>
>>>> an<br>
>>>> +    // lvalue-to-rvalue conversion.  Additionally, if it was a c++11<br>
>>>> constant<br>
>>>> +    // expression.<br>
>>>><br>
>>>> The added comment here doesn't look right; I think you should say<br>
>>>> something like "Even if we do not perform an lvalue-to-rvalue conversion, we<br>
>>>> pretend that one was performed when checking for odr-uses of variables."<br>
>>>><br>
>>>><br>
>>> Done.<br>
>>><br>
>>>><br>
>>>> Index: lib/CodeGen/CGExpr.cpp<br>
>>>> ===================================================================<br>
>>>><br>
>>>> You have CodeGen changes but no tests for them, please add some,<br>
>>>> covering all the ways in which a variable can be referenced without being<br>
>>>> odr-used.<br>
>>>><br>
>>><br>
>>> Still no codegen tests on this revision - will include them with my next<br>
>>> revision once i get your technical feedback on this one (and figure out the<br>
>>> LLVM IR i need to<br>
>>> ramp up on, so that I can start writing codegen tests for this).  Any<br>
>>> preliminary guidance will be appreciated.<br>
>>><br>
>>>><br>
>>>><br>
>>>> --- lib/CodeGen/CGExpr.cpp (revision 182855)<br>
>>>> +++ lib/CodeGen/CGExpr.cpp (working copy)<br>
>>>> @@ -1800,6 +1800,13 @@<br>
>>>>    return CGF.EmitLValueForField(LV, FD);<br>
>>>>  }<br>
>>>><br>
>>>> +<br>
>>>> +inline bool isLambdaCallOperator(const Decl *D) {<br>
>>>><br>
>>>> This seems generally useful; perhaps it should be a member of<br>
>>>> CXXMethodDecl? If not, s/inline/static/, please.<br>
>>>><br>
>>> This still needs to be done.<br>
>>><br>
>>>><br>
>>>><br>
>>>> +  if (!ND->isUsed(false) || (E->refersToEnclosingLocal() &&<br>
>>>> +                              isLambdaCallOperator(CurCodeDecl))) {<br>
>>>> +    if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {<br>
>>>><br>
>>>> Please flip these two 'if's around, and merge this into the preceding<br>
>>>> code (the end result should just be removing the isReferenceType() check<br>
>>>> from the preceding code block and adding the lambda-enclosing-local check).<br>
>>>><br>
>>>><br>
>>> Done.<br>
>>><br>
>>>><br>
>>>> @@ -2476,7 +2497,23 @@<br>
>>>><br>
>>>>  LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {<br>
>>>>    Expr *BaseExpr = E->getBase();<br>
>>>> +  ASTContext &Context = CGM.getContext();<br>
>>>> +  APValue ConstExprResult;<br>
>>>><br>
>>>> +  // Emit a field member access that evaluates to a constexpr s.x<br>
>>>> +  if (Context.getLangOpts().CPlusPlus11 &&<br>
>>>> E->isCXX11ConstantExpr(Context,<br>
>>>> +          &ConstExprResult)) {<br>
>>>> +    if (FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) {<br>
>>>> +      CharUnits Alignment = Context.getDeclAlign(FD);<br>
>>>> +      llvm::Constant *Val =<br>
>>>> +        CGM.EmitConstantValue(ConstExprResult, FD->getType(), this);<br>
>>>> +      assert(Val && "failed to emit C++11 constant member expression");<br>
>>>> +      // FIXME: Eventually we will want to emit vector element<br>
>>>> references.<br>
>>>> +      QualType T = E->getType();<br>
>>>> +      return MakeAddrLValue(Val, T, Alignment);<br>
>>>> +    }<br>
>>>> +  }<br>
>>>><br>
>>>> I don't think this approach can work. Consider this:<br>
>>>><br>
>>>>   struct S { int x; };<br>
>>>>   constexpr S a = { 1 };<br>
>>>>   S b = { 2 };<br>
>>>>   bool k;<br>
>>>>   return (k ? a : b).x;<br>
>>>><br>
>>>> This does not odr-use 'a', but it does odr-use 'b'. The MemberExpr is<br>
>>>> not a constant expression here. I think instead what you should do is to<br>
>>>> teach AggExprEmitter (and friends) to directly emit a constant value when<br>
>>>> they visit a DeclRefExpr which is not an odr-use<br>
>>>><br>
>>><br>
>>> I think I fixed this - but I must admit I was unable to figure out how to<br>
>>> fix it through AggExprEmitter.  My fix uses a visitor in<br>
>>> CodeGenFunction::EmitDeclRefExpr<br>
>>> to try and figure out whether the DeclRefExpr is in a conditional<br>
>>> operator context of an object expression of a member expression (which is<br>
>>> pushed onto a stack), and if<br>
>>> that is the case, it emits a pointer to the struct vs the constant<br>
>>> version of the struct.  It seems to pass my tests - but like i said earlier,<br>
>>> I have not had the time yet<br>
>>> to write the appropriate LLVM-IR codegen tests.  Please let me know about<br>
>>> the robustness of my fix - it does feel a little brittle to me.  If you<br>
>>> stiill feel<br>
>>> AggExprEmitter is the way to go with this, I could certainly use a little<br>
>>> guidance as to how we enter into AggExprEmitter while emitting code for the<br>
>>> conditional expr.<br>
>>><br>
>>>><br>
>>>><br>
>>>> @@ -3239,6 +3276,23 @@<br>
>>>>  LValue CodeGenFunction::<br>
>>>>  EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {<br>
>>>>    llvm::Value *BaseV;<br>
>>>> +<br>
>>>> +  Expr *ObjExpr = E->getLHS();<br>
>>>> +  ASTContext &Context = CGM.getContext();<br>
>>>> +  APValue ConstExprResult;<br>
>>>> +  // Emit a field member access that evaluates to a constexpr s.*memfn<br>
>>>> +  if (Context.getLangOpts().CPlusPlus11 &&<br>
>>>> E->isCXX11ConstantExpr(Context,<br>
>>>> +        &ConstExprResult)) {<br>
>>>> +    const MemberPointerType *MPT<br>
>>>> +                  = E->getRHS()->getType()->getAs<MemberPointerType>();<br>
>>>> +    llvm::Constant *Val =<br>
>>>> +      CGM.EmitConstantValue(ConstExprResult, MPT->getPointeeType(),<br>
>>>> this);<br>
>>>> +    assert(Val && "failed to emit C++11 constant member expression");<br>
>>>> +    // FIXME: Eventually we will want to emit vector element<br>
>>>> references.<br>
>>>> +    QualType T = E->getType();<br>
>>>> +    return MakeAddrLValue(Val, T);<br>
>>>> +  }<br>
>>>><br>
>>>> In this case, you should constant-evaluate the RHS but not the LHS.<br>
>>>> Also, use EvaluateAsRValue here; it doesn't matter whether we need to<br>
>>>> perform non-standard constant folding. And there's no need to check for<br>
>>>> C++11 mode.<br>
>>>><br>
>>>><br>
>>> Done.<br>
>>><br>
>>><br>
>>>><br>
>>>> Index: test/CXX/basic/basic.def.odr/p2-DR712-C++14-CD.cpp<br>
>>>> ===================================================================<br>
>>>> --- test/CXX/basic/basic.def.odr/p2-DR712-C++14-CD.cpp (revision 0)<br>
>>>> +++ test/CXX/basic/basic.def.odr/p2-DR712-C++14-CD.cpp (working copy)<br>
>>>><br>
>>>> Maybe just call this .../p2-potential-results.cpp -- this isn't<br>
>>>> C++1y-specific. This file contains both UTF-8 characters in comments and<br>
>>>> \r\n line separators, please fix.<br>
>>><br>
>>><br>
>>> Done.<br>
>>><br>
>>><br>
>>> Await your feedback ...<br>
>>><br>
>>> Also *ping* the patch<br>
>>> (<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>)<br>
>>> was LGTM'd by Doug, anyway we can get that one committed please - thank you!<br>
>>><br>
>>> Thanks again Richard!<br>
>>><br>
>>>><br>
>>>><br>
>>>>><br>
>>>>><br>
>>>>><br>
>>>>><br>
>>>>><br>
>>>>> On Sat, May 18, 2013 at 1:42 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>><br>
>>>>> wrote:<br>
>>>>>><br>
>>>>>> On Sat, May 18, 2013 at 9:22 AM, Faisal Vali <<a href="mailto:faisalv@gmail.com">faisalv@gmail.com</a>><br>
>>>>>> wrote:<br>
>>>>>>><br>
>>>>>>> Before I return to working on generic lambdas, I thought it might be<br>
>>>>>>> useful to nail down DR 712 which reworded the definition of odr-use in terms<br>
>>>>>>> of the potential results of an expression (in order to avoid odr-using a<br>
>>>>>>> variable that represents a constant expression whenever we can get away with<br>
>>>>>>> it).  This is relevant to lambdas, because it affects which variables get<br>
>>>>>>> captured and which don't.<br>
>>>>>>><br>
>>>>>>><br>
>>>>>>> Let me review how I think clang currently handles this (pre-712<br>
>>>>>>> resolution  - please correct me where I err). While parsing and semanalyzing<br>
>>>>>>> expressions, all variables that are usable in constant expressions (and so<br>
>>>>>>> might not need to be odr-used) are stored in MaybeODRUseExprs (a set<br>
>>>>>>> container) as DeclRefExprs (DRE).  Then, if an Lvalue-to-Rvalue conversion<br>
>>>>>>> is performed on the DRE, it is removed from the set above (In<br>
>>>>>>> UpdateMarkingForLValueToRValue).  Anything left in that set is marked as<br>
>>>>>>> odr-used by ActOnFinishFullExpr.<br>
>>>>>>><br>
>>>>>>><br>
>>>>>>> OK, with the above in mind, these are my initial thoughts on how to<br>
>>>>>>> implement it so that not only do we handle those constant expressions that<br>
>>>>>>> are lvalue-to-rvalue converted, but also those that are discarded, and also<br>
>>>>>>> handle the conditional expressions and member-access expressions.<br>
>>>>>>><br>
>>>>>>> The relevant hooks/callbacks/functions within clang are:<br>
>>>>>>>   - UpdateMarkingForLValueToRValue<br>
>>>>>>>   - IgnoredValueConversions<br>
>>>>>>><br>
>>>>>>> A function i intend to write is GetPotentialResultsOfExpression: when<br>
>>>>>>> passed an Expr* E, returns a vector of its potential results as<br>
>>>>>>> DeclRefExpr's (and MemberExpr's??); this function should follow from  3.2<br>
>>>>>>> para 2.<br>
>>>>>>><br>
>>>>>>> Now in each hook, GetPotentialResults shall be called, and those<br>
>>>>>>> expressions shall be removed from the MaybeODRUseExpr.<br>
>>>>>><br>
>>>>>><br>
>>>>>> This seems like the right approach, although you presumably don't<br>
>>>>>> actually need to build the vector and could just remove the odr-use marker<br>
>>>>>> directly.<br>
>>>>>><br>
>>>>>>><br>
>>>>>>> What are your thoughts on the above preliminary strategy?  I have<br>
>>>>>>> this sense that Member expressions are going to require some more work, but<br>
>>>>>>> we'll see...<br>
>>>>>>><br>
>>>>>>> Also before I proceed any further, I was hoping to get some more<br>
>>>>>>> clarity on 3.2 para 2 and para 3 - please see my queries below:<br>
>>>>>>><br>
>>>>>>><br>
>>>>>>> Consider the following code:<br>
>>>>>>><br>
>>>>>>><br>
>>>>>>> struct S {<br>
>>>>>>>   const int mi;<br>
>>>>>>>   constexpr S(int i) : mi(i) { }<br>
>>>>>>> };<br>
>>>>>>><br>
>>>>>>> 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>
>>>>>><br>
>>>>>><br>
>>>>>> No. Here, e = 's.mi', ex = 's' (a member of the set of potential<br>
>>>>>> results of e), and e is subject to an lvalue-to-rvalue conversion.<br>
>>>>>><br>
>>>>>>><br>
>>>>>>>       g(s.mi);   //  #2 what about this?<br>
>>>>>><br>
>>>>>><br>
>>>>>> Also no, because an lvalue-to-rvalue conversion is applied to s.mi.<br>
>>>>>><br>
>>>>>>><br>
>>>>>>>       s.mi;        // #3 and this?<br>
>>>>>><br>
>>>>>><br>
>>>>>> Also no, because this is a discarded-value expression.<br>
>>>>>><br>
>>>>>>><br>
>>>>>>>       c ? s.mi : r.mi; // #4 and this?<br>
>>>>>><br>
>>>>>><br>
>>>>>> Also no.<br>
>>>>>><br>
>>>>>>><br>
>>>>>>>       g( c ? s.mi : r.mi ); // #5<br>
>>>>>><br>
>>>>>><br>
>>>>>> Also no.<br>
>>>>>><br>
>>>>>>><br>
>>>>>>>   };<br>
>>>>>>> }<br>
>>>>>>><br>
>>>>>>> My intial suspicion was that neither s nor r were odr-used in the<br>
>>>>>>> lambda (because the compiler can figure out the value of 'mi' at its point<br>
>>>>>>> of use, and use it or discard it) - but then based on Richard's analysis of<br>
>>>>>>> the example below where he states that s.operator int() is an odr-use of<br>
>>>>>>> 's', i am now unsure.<br>
>>>>>><br>
>>>>>><br>
>>>>>> Note that member function calls aren't listed in the rules of 3.2/2.<br>
>>>>>> 's' is not in the set of potential results of 's.operator int()'.<br>
>>>>>><br>
>>>>>>><br>
>>>>>>> Here is my attempt at trying to figure this out (e refers to<br>
>>>>>>> expression, ex as a potentially-evaluated expression, using the language of<br>
>>>>>>> 3.2 para 2 and 3)<br>
>>>>>>><br>
>>>>>>> In #1,<br>
>>>>>>>   the variable 's' appears as a potentially evaluated expression and<br>
>>>>>>> satisfies the requirements for appearing in a constant expression, and it is<br>
>>>>>>> an object, and it is an element of the set of potential results of an<br>
>>>>>>> expression 'e' (s.mi) and the lvalue-to-rvalue conversion is applied to that<br>
>>>>>>> expression so it is not odr-used?  But what if 'e' is deemed to be 's' in<br>
>>>>>>> 's.mi' - no lvalue-to-rvalue conversion is applied so it should be captured?<br>
>>>>>><br>
>>>>>><br>
>>>>>> The rule says: "x [...] is odr-used unless [...] ex is is an element<br>
>>>>>> of the set of potential results of an expression e, where [...]"<br>
>>>>>><br>
>>>>>> That is, if there *exists* such an 'e', then 'x' is not odr-used.<br>
>>>>>><br>
>>>>>> Hope that helps!<br>
>>>>>><br>
>>>>>>><br>
>>>>>>> OK, I'm going to give up on analyzing the rest, because I feel I'm<br>
>>>>>>> missing something and am unable to think about this clearly.<br>
>>>>>>><br>
>>>>>>> Any help or guidance will be appreciated!<br>
>>>>>>><br>
>>>>>>><br>
>>>>>>><br>
>>>>>>> On Wed, May 15, 2013 at 3:21 PM, Richard Smith<br>
>>>>>>> <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>> wrote:<br>
>>>>>>>><br>
>>>>>>>> On Tue, May 14, 2013 at 9:48 PM, Faisal Vali <<a href="mailto:faisalv@gmail.com">faisalv@gmail.com</a>><br>
>>>>>>>> wrote:<br>
>>>>>>>>><br>
>>>>>>>>><br>
>>>>>>>>><br>
>>>>>>>>> While we're on the topic, can i ask you to clarify a few capture<br>
>>>>>>>>> and constexpr<br>
>>>>>>>>> questions below:<br>
>>>>>>>><br>
>>>>>>>><br>
>>>>>>>> OK, the relevant context is [basic.def.odr]p2 and p3.<br>
>>>>>>>><br>
>>>>>>>>><br>
>>>>>>>>> struct S {<br>
>>>>>>>>>   constexpr S() {}<br>
>>>>>>>>>   constexpr operator int() const { return 0; }<br>
>>>>>>>>> };<br>
>>>>>>>>> void fooS(S s) { }<br>
>>>>>>>>><br>
>>>>>>>>> void fooInt(int i) { }<br>
>>>>>>>>><br>
>>>>>>>>> void f() {<br>
>>>>>>>>>   constexpr S s {};<br>
>>>>>>>>>   auto L = [] (int x) {<br>
>>>>>>>>>       (void) s;  // 1<br>
>>>>>>>><br>
>>>>>>>><br>
>>>>>>>> Here, the 's' expression is a discarded-value expression, and the<br>
>>>>>>>> 's' variable is in the set of potential results of the 's' expression, and<br>
>>>>>>>> 's' satisfies the constraints for appearing in a constant expression, so 's'<br>
>>>>>>>> is not odr-used, so is not captured. We should not require a capture-default<br>
>>>>>>>> here.<br>
>>>>>>>><br>
>>>>>>>>><br>
>>>>>>>>>       fooS(s);  // 2<br>
>>>>>>>><br>
>>>>>>>><br>
>>>>>>>> Here, 's' is implicitly passed to the implicit S::S(const S&)<br>
>>>>>>>> constructor. This is neither an lvalue-to-rvalue conversion nor a<br>
>>>>>>>> discarded-value expression, so 's' is odr-used and we have an error due to<br>
>>>>>>>> the missing capture-default.<br>
>>>>>>>><br>
>>>>>>>>><br>
>>>>>>>>>       fooInt(s); // 3<br>
>>>>>>>><br>
>>>>>>>><br>
>>>>>>>> This is equivalent to 's.operator int()', which again odr-uses 's',<br>
>>>>>>>> so requires a capture-default.<br>
>>>>>>>><br>
>>>>>>>>><br>
>>>>>>>>>   };<br>
>>>>>>>>> }<br>
>>>>>>>>><br>
>>>>>>>>> Should the above be ok in spite of L not having a default capture?<br>
>>>>>>>>> Currently clang errors on all of them individually - is that the<br>
>>>>>>>>> right behavior?<br>
>>>>>>>>><br>
>>>>>>>>> Also, how would you want me to start submitting patches for commit<br>
>>>>>>>>> - do you want<br>
>>>>>>>>> me to break up the patch into smaller patches? - and if so, do you<br>
>>>>>>>>> have any thoughts<br>
>>>>>>>>> on how I might want to break up the functionality per patch?<br>
>>>>>>>><br>
>>>>>>>><br>
>>>>>>>> Smaller patches are definitely better, if you can decompose the<br>
>>>>>>>> functionality into coherent smaller chunks. There are some hints on how to<br>
>>>>>>>> decompose the functionality here (but this division may or may not work for<br>
>>>>>>>> you):<br>
>>>>>>>><br>
>>>>>>>><br>
>>>>>>>> <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><br>

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