[Sema] Add variable captured by a block to the enclosing lambda's

potential capture list.

Fix Sema::getCurLambda() to return the innermost lambda scope when there
is a block enclosed in the lambda. Previously, the method would return a
nullptr in such cases, which would prevent a variable captured by the
enclosed block to be added to the lambda scope's potential capture list.

rdar://problem/28412462

Differential Revision: https://reviews.llvm.org/D25556

llvm-svn: 296584
This commit is contained in:
Akira Hatanaka 2017-03-01 06:11:25 +00:00
parent 1a1d959423
commit 7cbbb88f23
4 changed files with 23 additions and 9 deletions

View File

@ -1244,9 +1244,11 @@ public:
sema::BlockScopeInfo *getCurBlock(); sema::BlockScopeInfo *getCurBlock();
/// Retrieve the current lambda scope info, if any. /// Retrieve the current lambda scope info, if any.
/// \param IgnoreCapturedRegions true if should find the top-most lambda scope /// \param IgnoreNonLambdaCapturingScope true if should find the top-most
/// info ignoring all inner captured regions scope infos. /// lambda scope info ignoring all inner capturing scopes that are not
sema::LambdaScopeInfo *getCurLambda(bool IgnoreCapturedRegions = false); /// lambda scopes.
sema::LambdaScopeInfo *
getCurLambda(bool IgnoreNonLambdaCapturingScope = false);
/// \brief Retrieve the current generic lambda info, if any. /// \brief Retrieve the current generic lambda info, if any.
sema::LambdaScopeInfo *getCurGenericLambda(); sema::LambdaScopeInfo *getCurGenericLambda();

View File

@ -1237,14 +1237,14 @@ BlockScopeInfo *Sema::getCurBlock() {
return CurBSI; return CurBSI;
} }
LambdaScopeInfo *Sema::getCurLambda(bool IgnoreCapturedRegions) { LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
if (FunctionScopes.empty()) if (FunctionScopes.empty())
return nullptr; return nullptr;
auto I = FunctionScopes.rbegin(); auto I = FunctionScopes.rbegin();
if (IgnoreCapturedRegions) { if (IgnoreNonLambdaCapturingScope) {
auto E = FunctionScopes.rend(); auto E = FunctionScopes.rend();
while (I != E && isa<CapturedRegionScopeInfo>(*I)) while (I != E && isa<CapturingScopeInfo>(*I) && !isa<LambdaScopeInfo>(*I))
++I; ++I;
if (I == E) if (I == E)
return nullptr; return nullptr;

View File

@ -14303,8 +14303,9 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
(SemaRef.CurContext != Var->getDeclContext() && (SemaRef.CurContext != Var->getDeclContext() &&
Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage()); Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage());
if (RefersToEnclosingScope) { if (RefersToEnclosingScope) {
if (LambdaScopeInfo *const LSI = LambdaScopeInfo *const LSI =
SemaRef.getCurLambda(/*IgnoreCapturedRegions=*/true)) { SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true);
if (LSI && !LSI->CallOperator->Encloses(Var->getDeclContext())) {
// If a variable could potentially be odr-used, defer marking it so // If a variable could potentially be odr-used, defer marking it so
// until we finish analyzing the full expression for any // until we finish analyzing the full expression for any
// lvalue-to-rvalue // lvalue-to-rvalue

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class -std=c++11 %s // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class -std=c++14 %s
@protocol NSObject; @protocol NSObject;
void bar(id(^)(void)); void bar(id(^)(void));
@ -145,6 +145,17 @@ namespace DependentReturn {
template void f<X>(X); template void f<X>(X);
} }
namespace GenericLambdaCapture {
int test(int outerp) {
auto lambda =[&](auto p) {
return ^{
return p + outerp;
}();
};
return lambda(1);
}
}
namespace MoveBlockVariable { namespace MoveBlockVariable {
struct B0 { struct B0 {
}; };