Author: epilk Date: Wed Jul 27 13:25:10 2016 New Revision: 276900 URL: http://llvm.org/viewvc/llvm-project?rev=276900&view=rev Log: [Sema] Teach getCurrentThisType to reconize lambda in in-class initializer
Fixes PR27994, a crash on valid. Differential revision: https://reviews.llvm.org/D21145 Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/test/SemaCXX/lambda-expressions.cpp Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=276900&r1=276899&r2=276900&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Jul 27 13:25:10 2016 @@ -961,32 +961,26 @@ static QualType adjustCVQualifiersForCXX QualType Sema::getCurrentThisType() { DeclContext *DC = getFunctionLevelDeclContext(); QualType ThisTy = CXXThisTypeOverride; + if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) { if (method && method->isInstance()) ThisTy = method->getThisType(Context); } - if (ThisTy.isNull()) { - if (isGenericLambdaCallOperatorSpecialization(CurContext) && - CurContext->getParent()->getParent()->isRecord()) { - // This is a generic lambda call operator that is being instantiated - // within a default initializer - so use the enclosing class as 'this'. - // There is no enclosing member function to retrieve the 'this' pointer - // from. - - // FIXME: This looks wrong. If we're in a lambda within a lambda within a - // default member initializer, we need to recurse up more parents to find - // the right context. Looks like we should be walking up to the parent of - // the closure type, checking whether that is itself a lambda, and if so, - // recursing, until we reach a class or a function that isn't a lambda - // call operator. And we should accumulate the constness of *this on the - // way. - - QualType ClassTy = Context.getTypeDeclType( - cast<CXXRecordDecl>(CurContext->getParent()->getParent())); - // There are no cv-qualifiers for 'this' within default initializers, - // per [expr.prim.general]p4. - ThisTy = Context.getPointerType(ClassTy); - } + + if (ThisTy.isNull() && isLambdaCallOperator(CurContext) && + !ActiveTemplateInstantiations.empty()) { + + assert(isa<CXXRecordDecl>(DC) && + "Trying to get 'this' type from static method?"); + + // This is a lambda call operator that is being instantiated as a default + // initializer. DC must point to the enclosing class type, so we can recover + // the 'this' type from it. + + QualType ClassTy = Context.getTypeDeclType(cast<CXXRecordDecl>(DC)); + // There are no cv-qualifiers for 'this' within default initializers, + // per [expr.prim.general]p4. + ThisTy = Context.getPointerType(ClassTy); } // If we are within a lambda's call operator, the cv-qualifiers of 'this' Modified: cfe/trunk/test/SemaCXX/lambda-expressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=276900&r1=276899&r2=276900&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/lambda-expressions.cpp (original) +++ cfe/trunk/test/SemaCXX/lambda-expressions.cpp Wed Jul 27 13:25:10 2016 @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify -fblocks %s -// RUN: %clang_cc1 -std=c++1y -Wno-unused-value -fsyntax-only -verify -fblocks %s +// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -fblocks %s namespace std { class type_info; }; @@ -499,3 +498,30 @@ void foo() { }; } } + +namespace PR27994 { +struct A { template <class T> A(T); }; + +template <class T> +struct B { + int x; + A a = [&] { int y = x; }; + A b = [&] { [&] { [&] { int y = x; }; }; }; + A d = [&](auto param) { int y = x; }; + A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; }; +}; + +B<int> b; + +template <class T> struct C { + struct D { + int x; + A f = [&] { int y = x; }; + }; +}; + +int func() { + C<int> a; + decltype(a)::D b; +} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits