ahatanak created this revision. ahatanak added reviewers: rsmith, rjmccall. ahatanak added a subscriber: cfe-commits.
When compiling the following code, DoMarkVarDeclReferenced fails to capture variable "outerp": auto lambda =[&](auto p) { return ^{ return p + outerp; }(); }; This happens because Sema::getCurLambda() returns the lambda scope only when it's the last scope that has been pushed to Sema::FunctionScopes and therefore returns null if there is a block enclosed in the lambda. To fix this bug, this patch defines function Sema::getInnermostLambda() and uses it in DoMarkVarDeclReferenced to get the innermost lambda scope. rdar://problem/28412462 https://reviews.llvm.org/D25556 Files: include/clang/Sema/Sema.h lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp test/SemaObjCXX/blocks.mm Index: test/SemaObjCXX/blocks.mm =================================================================== --- test/SemaObjCXX/blocks.mm +++ test/SemaObjCXX/blocks.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class %s +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class -std=c++14 %s @protocol NSObject; void bar(id(^)(void)); @@ -144,3 +144,14 @@ template void f<X>(X); } + +namespace GenericLambdaCapture { + int test(int outerp) { + auto lambda =[&](auto p) { + return ^{ + return p + outerp; + }(); + }; + return lambda(1); + } +} Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -14013,7 +14013,7 @@ (SemaRef.CurContext != Var->getDeclContext() && Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage()); if (RefersToEnclosingScope) { - if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) { + if (LambdaScopeInfo *const LSI = SemaRef.getInnermostLambda()) { // If a variable could potentially be odr-used, defer marking it so // until we finish analyzing the full expression for any // lvalue-to-rvalue Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -1220,6 +1220,13 @@ return nullptr; } +LambdaScopeInfo *Sema::getInnermostLambda() { + for (auto I = FunctionScopes.rbegin(), E = FunctionScopes.rend(); I != E; ++I) + if (auto LSI = dyn_cast<LambdaScopeInfo>(*I)) + return LSI; + + return nullptr; +} void Sema::ActOnComment(SourceRange Comment) { if (!LangOpts.RetainCommentsFromSystemHeaders && Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -1247,6 +1247,9 @@ /// \brief Retrieve the current generic lambda info, if any. sema::LambdaScopeInfo *getCurGenericLambda(); + /// Retrieve the innermost lambda scope info, if any. + sema::LambdaScopeInfo *getInnermostLambda(); + /// \brief Retrieve the current captured region, if any. sema::CapturedRegionScopeInfo *getCurCapturedRegion();
Index: test/SemaObjCXX/blocks.mm =================================================================== --- test/SemaObjCXX/blocks.mm +++ test/SemaObjCXX/blocks.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class %s +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class -std=c++14 %s @protocol NSObject; void bar(id(^)(void)); @@ -144,3 +144,14 @@ template void f<X>(X); } + +namespace GenericLambdaCapture { + int test(int outerp) { + auto lambda =[&](auto p) { + return ^{ + return p + outerp; + }(); + }; + return lambda(1); + } +} Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -14013,7 +14013,7 @@ (SemaRef.CurContext != Var->getDeclContext() && Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage()); if (RefersToEnclosingScope) { - if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) { + if (LambdaScopeInfo *const LSI = SemaRef.getInnermostLambda()) { // If a variable could potentially be odr-used, defer marking it so // until we finish analyzing the full expression for any // lvalue-to-rvalue Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -1220,6 +1220,13 @@ return nullptr; } +LambdaScopeInfo *Sema::getInnermostLambda() { + for (auto I = FunctionScopes.rbegin(), E = FunctionScopes.rend(); I != E; ++I) + if (auto LSI = dyn_cast<LambdaScopeInfo>(*I)) + return LSI; + + return nullptr; +} void Sema::ActOnComment(SourceRange Comment) { if (!LangOpts.RetainCommentsFromSystemHeaders && Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -1247,6 +1247,9 @@ /// \brief Retrieve the current generic lambda info, if any. sema::LambdaScopeInfo *getCurGenericLambda(); + /// Retrieve the innermost lambda scope info, if any. + sema::LambdaScopeInfo *getInnermostLambda(); + /// \brief Retrieve the current captured region, if any. sema::CapturedRegionScopeInfo *getCurCapturedRegion();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits