summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2016-08-11 18:13:48 +0000
committerHans Wennborg <hans@hanshq.net>2016-08-11 18:13:48 +0000
commit8d6233930898d5855576777871a64c7f0cd225cc (patch)
tree0a90f3f415417e2fb5362df5dbd8987a4f65ec90
parent959e1a652e93707bbbe2d6134953257ebe904360 (diff)
Merging r276900:
------------------------------------------------------------------------ r276900 | epilk | 2016-07-27 11:25:10 -0700 (Wed, 27 Jul 2016) | 5 lines [Sema] Teach getCurrentThisType to reconize lambda in in-class initializer Fixes PR27994, a crash on valid. Differential revision: https://reviews.llvm.org/D21145 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_39@278374 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaExprCXX.cpp38
-rw-r--r--test/SemaCXX/lambda-expressions.cpp30
2 files changed, 44 insertions, 24 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 2cd00f8218..b7a968e09d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -961,32 +961,26 @@ static QualType adjustCVQualifiersForCXXThisWithinLambda(
QualType Sema::getCurrentThisType() {
DeclContext *DC = getFunctionLevelDeclContext();
QualType ThisTy = CXXThisTypeOverride;
+
if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
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()) {
+
+ assert(isa<CXXRecordDecl>(DC) &&
+ "Trying to get 'this' type from static method?");
+
+ // This is a lambda call operator that is being instantiated as a default
+ // initializer. DC must point to the enclosing class type, so we can recover
+ // the 'this' type from it.
+
+ QualType ClassTy = Context.getTypeDeclType(cast<CXXRecordDecl>(DC));
+ // 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'
diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp
index 17808cef36..5fffe41117 100644
--- a/test/SemaCXX/lambda-expressions.cpp
+++ b/test/SemaCXX/lambda-expressions.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify -fblocks %s
-// RUN: %clang_cc1 -std=c++1y -Wno-unused-value -fsyntax-only -verify -fblocks %s
+// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -fblocks %s
namespace std { class type_info; };
@@ -499,3 +498,30 @@ void foo() {
};
}
}
+
+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;
+}
+}