r209874 - Fix 'this' capturing Generic lambdas used within default initializers (PR19876)

Faisal Vali faisalv at yahoo.com
Thu May 29 21:39:38 PDT 2014


Author: faisalv
Date: Thu May 29 23:39:37 2014
New Revision: 209874

URL: http://llvm.org/viewvc/llvm-project?rev=209874&view=rev
Log:
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!


Modified:
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=209874&r1=209873&r2=209874&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu May 29 23:39:37 2014
@@ -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<CXXRecordDecl>(CurContext->getParent()->getParent()));
+      // There are no cv-qualifiers for 'this' within default initializers, 
+      // per [expr.prim.general]p4.
+      return Context.getPointerType(ClassTy);
+    }
+  }
   return ThisTy;
 }
 

Modified: cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp?rev=209874&r1=209873&r2=209874&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp Thu May 29 23:39:37 2014
@@ -1358,6 +1358,21 @@ template<class R> struct X {
 int run_char = X<int>{}.foo('a');
 int run_int = X<double>{}.foo(4);
 }
-
 #endif // MS_EXTENSIONS
 
+namespace nsdmi_capturing_this {
+struct X {
+  int m = 10;
+  int n = [this](auto) { return m; }(20);
+};
+
+template<class T>
+struct XT {
+  T m = 10;
+  T n = [this](auto) { return m; }(20);
+};
+
+XT<int> xt{};
+
+
+}





More information about the cfe-commits mailing list