<div dir="ltr">Yes, this should be merged. It's not quite right, but it's certainly better than what we had before.<br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Aug 8, 2016 at 1:34 PM, Hans Wennborg <span dir="ltr"><<a href="mailto:hans@chromium.org" target="_blank">hans@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Richard: ping?<br>
<div class="HOEnZb"><div class="h5"><br>
On Wed, Jul 27, 2016 at 4:46 PM, Hans Wennborg <<a href="mailto:hans@chromium.org">hans@chromium.org</a>> wrote:<br>
> Should this be merged to 3.9?<br>
><br>
> Thanks,<br>
> Hans<br>
><br>
> On Wed, Jul 27, 2016 at 11:25 AM, Erik Pilkington via cfe-commits<br>
> <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br>
>> Author: epilk<br>
>> Date: Wed Jul 27 13:25:10 2016<br>
>> New Revision: 276900<br>
>><br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=276900&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=276900&view=rev</a><br>
>> Log:<br>
>> [Sema] Teach getCurrentThisType to reconize lambda in in-class initializer<br>
>><br>
>> Fixes PR27994, a crash on valid.<br>
>><br>
>> Differential revision: <a href="https://reviews.llvm.org/D21145" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D21145</a><br>
>><br>
>> Modified:<br>
>> cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp<br>
>> cfe/trunk/test/SemaCXX/lambda-<wbr>expressions.cpp<br>
>><br>
>> Modified: cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=276900&r1=276899&r2=276900&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp?rev=276900&r1=<wbr>276899&r2=276900&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp (original)<br>
>> +++ cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp Wed Jul 27 13:25:10 2016<br>
>> @@ -961,32 +961,26 @@ static QualType adjustCVQualifiersForCXX<br>
>> QualType Sema::getCurrentThisType() {<br>
>> DeclContext *DC = getFunctionLevelDeclContext();<br>
>> QualType ThisTy = CXXThisTypeOverride;<br>
>> +<br>
>> if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {<br>
>> if (method && method->isInstance())<br>
>> ThisTy = method->getThisType(Context);<br>
>> }<br>
>> - if (ThisTy.isNull()) {<br>
>> - if (<wbr>isGenericLambdaCallOperatorSpe<wbr>cialization(CurContext) &&<br>
>> - CurContext->getParent()-><wbr>getParent()->isRecord()) {<br>
>> - // This is a generic lambda call operator that is being instantiated<br>
>> - // within a default initializer - so use the enclosing class as 'this'.<br>
>> - // There is no enclosing member function to retrieve the 'this' pointer<br>
>> - // from.<br>
>> -<br>
>> - // FIXME: This looks wrong. If we're in a lambda within a lambda within a<br>
>> - // default member initializer, we need to recurse up more parents to find<br>
>> - // the right context. Looks like we should be walking up to the parent of<br>
>> - // the closure type, checking whether that is itself a lambda, and if so,<br>
>> - // recursing, until we reach a class or a function that isn't a lambda<br>
>> - // call operator. And we should accumulate the constness of *this on the<br>
>> - // way.<br>
>> -<br>
>> - QualType ClassTy = Context.getTypeDeclType(<br>
>> - cast<CXXRecordDecl>(<wbr>CurContext->getParent()-><wbr>getParent()));<br>
>> - // There are no cv-qualifiers for 'this' within default initializers,<br>
>> - // per [expr.prim.general]p4.<br>
>> - ThisTy = Context.getPointerType(<wbr>ClassTy);<br>
>> - }<br>
>> +<br>
>> + if (ThisTy.isNull() && isLambdaCallOperator(<wbr>CurContext) &&<br>
>> + !ActiveTemplateInstantiations.<wbr>empty()) {<br>
>> +<br>
>> + assert(isa<CXXRecordDecl>(DC) &&<br>
>> + "Trying to get 'this' type from static method?");<br>
>> +<br>
>> + // This is a lambda call operator that is being instantiated as a default<br>
>> + // initializer. DC must point to the enclosing class type, so we can recover<br>
>> + // the 'this' type from it.<br>
>> +<br>
>> + QualType ClassTy = Context.getTypeDeclType(cast<<wbr>CXXRecordDecl>(DC));<br>
>> + // There are no cv-qualifiers for 'this' within default initializers,<br>
>> + // per [expr.prim.general]p4.<br></div></div></blockquote><div><br></div><div>This is wrong in C++17 onwards: if *this is captured by value by a non-mutable lambda, it should become const-qualified.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">
>> + ThisTy = Context.getPointerType(<wbr>ClassTy);<br>
>> }<br>
>><br>
>> // If we are within a lambda's call operator, the cv-qualifiers of 'this'<br>
>><br>
>> Modified: cfe/trunk/test/SemaCXX/lambda-<wbr>expressions.cpp<br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=276900&r1=276899&r2=276900&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaCXX/lambda-expressions.<wbr>cpp?rev=276900&r1=276899&r2=<wbr>276900&view=diff</a><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/SemaCXX/lambda-<wbr>expressions.cpp (original)<br>
>> +++ cfe/trunk/test/SemaCXX/lambda-<wbr>expressions.cpp Wed Jul 27 13:25:10 2016<br>
>> @@ -1,5 +1,4 @@<br>
>> -// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify -fblocks %s<br>
>> -// RUN: %clang_cc1 -std=c++1y -Wno-unused-value -fsyntax-only -verify -fblocks %s<br>
>> +// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -fblocks %s<br>
>><br>
>> namespace std { class type_info; };<br>
>><br>
>> @@ -499,3 +498,30 @@ void foo() {<br>
>> };<br>
>> }<br>
>> }<br>
>> +<br>
>> +namespace PR27994 {<br>
>> +struct A { template <class T> A(T); };<br>
>> +<br>
>> +template <class T><br>
>> +struct B {<br>
>> + int x;<br>
>> + A a = [&] { int y = x; };<br>
>> + A b = [&] { [&] { [&] { int y = x; }; }; };<br>
>> + A d = [&](auto param) { int y = x; };<br>
>> + A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; };<br>
>> +};<br>
>> +<br>
>> +B<int> b;<br>
>> +<br>
>> +template <class T> struct C {<br>
>> + struct D {<br>
>> + int x;<br>
>> + A f = [&] { int y = x; };<br>
>> + };<br>
>> +};<br>
>> +<br>
>> +int func() {<br>
>> + C<int> a;<br>
>> + decltype(a)::D b;<br>
>> +}<br>
>> +}<br>
>><br>
>><br>
>> ______________________________<wbr>_________________<br>
>> cfe-commits mailing list<br>
>> <a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
>> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</div></div></blockquote></div><br></div></div>