[PATCH] [PATCH] Fix PR19876 - Generic lambdas that capture 'this' used within NSDMIs result in a crash

Faisal Vali faisalv at gmail.com
Tue May 27 22:39:04 PDT 2014


Hi rsmith, doug.gregor,

See 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);
};

This is because when implicitly instantiating the generic lambda's call operator specialization body, Sema gets confused and is unable to determine the current 'this' type when transforming the MemberExpr 'm'.
That is SemaExprCXX.cpp:Sema::getCurrentThisType() is unable to calculate that the this type should be X* since it looks for the nearest enclosing FunctionDeclDC - which is obviously null.


I suppose there are 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 and return the appropriate this type.

I am not sure which way is definitely better - but either one seemed easy to implement.
I chose #2 - although I can't think of a good reason for choosing it over #1.  
Feedback will be welcome  - and especially if there is another option that might be even more robust.

Thanks!

http://reviews.llvm.org/D3935

Files:
  lib/Sema/SemaExprCXX.cpp
  test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp

Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp
+++ 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"
@@ -736,7 +737,20 @@
     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 an NSDMI - 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()));
+      // Unlike for within methods, we don't have to worry about adding
+      // CVR qualifications in this context.  Just get the pointer to
+      // the enclosing class.
+      return Context.getPointerType(ClassTy);
+    }
+  }
   return ThisTy;
 }
 
Index: test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
===================================================================
--- test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
+++ test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
@@ -1358,6 +1358,21 @@
 int run_char = X<int>{}.foo('a');
 int run_int = X<double>{}.foo(4);
 }
+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{};
+
+
+}
 #endif // MS_EXTENSIONS
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3935.9862.patch
Type: text/x-patch
Size: 1869 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140528/d2734f75/attachment.bin>


More information about the cfe-commits mailing list