From 47d9ed4e2005795cb1565a5ec1952cabf777ad62 Mon Sep 17 00:00:00 2001 From: Faisal Vali Date: Fri, 30 May 2014 04:39:37 +0000 Subject: [PATCH] Fix 'this' capturing Generic lambdas used within default initializers (PR19876) http://llvm.org/bugs/show_bug.cgi?id=19876 The following C++1y code results in a crash: struct X { int m = 10; int n = [this](auto) { return m; }(20); }; When implicitly instantiating the generic lambda's call operator specialization body, Sema is unable to determine the current 'this' type when transforming the MemberExpr 'm' - since it looks for the nearest enclosing FunctionDeclDC - which is obviously null. I considered two ways to fix this: 1) In InstantiateFunctionDefinition, when the context is saved after the lambda scope info is created, retain the 'this' pointer. 2) Teach getCurrentThisType() to recognize it is within a generic lambda within an NSDMI/default-initializer and return the appropriate this type. I chose to implement #2 (though I confess I do not have a compelling reason for choosing it over #1). Richard Smith accepted the patch: http://reviews.llvm.org/D3935 Thank you! llvm-svn: 209874 --- clang/lib/Sema/SemaExprCXX.cpp | 16 +++++++++++++++- clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp | 17 ++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 6ebe974..41eceb1 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -15,6 +15,7 @@ #include "clang/Sema/SemaInternal.h" #include "TypeLocBuilder.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" @@ -732,7 +733,20 @@ QualType Sema::getCurrentThisType() { 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. + QualType ClassTy = Context.getTypeDeclType( + cast(CurContext->getParent()->getParent())); + // There are no cv-qualifiers for 'this' within default initializers, + // per [expr.prim.general]p4. + return Context.getPointerType(ClassTy); + } + } return ThisTy; } diff --git a/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp b/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp index 8bd4f42..b08d58a 100644 --- a/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp +++ b/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp @@ -1358,6 +1358,21 @@ template struct X { int run_char = X{}.foo('a'); int run_int = X{}.foo(4); } - #endif // MS_EXTENSIONS +namespace nsdmi_capturing_this { +struct X { + int m = 10; + int n = [this](auto) { return m; }(20); +}; + +template +struct XT { + T m = 10; + T n = [this](auto) { return m; }(20); +}; + +XT xt{}; + + +} -- 2.7.4