[PATCH] D21145: [Sema] Fix crash on valid where instantiation of lambda cannot access type of 'this'
Erik Pilkington via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 12 13:00:40 PDT 2016
erik.pilkington updated this revision to Diff 60477.
erik.pilkington added a comment.
This new patch changes `Sema::getCurrentThisType` to recover the `this` type when a lambda initializer is being transformed. This is done with the same code as when instantiating a generic lambda initializer. I also added a loop that finds the enclosing record, in the case where we need to access the `this` type through a nested lambda.
Thanks for the feedback!
http://reviews.llvm.org/D21145
Files:
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/lambda-expressions.cpp
Index: test/SemaCXX/lambda-expressions.cpp
===================================================================
--- test/SemaCXX/lambda-expressions.cpp
+++ test/SemaCXX/lambda-expressions.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify -fblocks %s
+// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -fblocks %s
// RUN: %clang_cc1 -std=c++1y -Wno-unused-value -fsyntax-only -verify -fblocks %s
namespace std { class type_info; };
@@ -499,3 +499,30 @@
};
}
}
+
+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;
+}
+}
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -965,28 +965,33 @@
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()) {
+
+ // This is a lambda call operator that is being instantiated as a default
+ // initializer. We need to iterate through the potential list of parent
+ // lambda contexts to reach the enclosing class, from which we can recover
+ // the 'this' pointer type, as there is no enclosing member function.
+
+ DeclContext *IterCtx = CurContext;
+ for (;;) {
+ // Jump over both the lambda call operator and the lambda class.
+ IterCtx = IterCtx->getParent()->getParent();
+
+ if (IterCtx->isRecord())
+ break;
+
+ // FIXME: Is this possible?
+ if (!(isa<CXXMethodDecl>(IterCtx) &&
+ cast<CXXRecordDecl>(IterCtx->getParent())->isLambda()))
+ return QualType();
}
+
+ QualType ClassTy = Context.getTypeDeclType(cast<CXXRecordDecl>(IterCtx));
+ // 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'
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D21145.60477.patch
Type: text/x-patch
Size: 3623 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160612/6bde6779/attachment.bin>
More information about the cfe-commits
mailing list