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