Author: abataev Date: Tue Nov 15 08:23:10 2016 New Revision: 286966 URL: http://llvm.org/viewvc/llvm-project?rev=286966&view=rev Log: Merging r286584: ------------------------------------------------------------------------ r286584 | abataev | 2016-11-11 12:36:20 +0000 (Fri, 11 Nov 2016) | 31 lines
Fix for PR28523: unexpected compilation error. Clang emits error message for the following code: ``` template <class F> void parallel_loop(F &&f) { f(0); } int main() { int x; parallel_loop([&](auto y) { { x = y; }; }); } ``` $ clang++ --std=gnu++14 clang_test.cc -o clang_test clang_test.cc:9:7: error: reference to local variable 'x' declared in enclosing function 'main' x = y; ^ clang_test.cc:2:48: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<int>' requested here template <class F> void parallel_loop(F &&f) { f(0); } ^ clang_test.cc:6:3: note: in instantiation of function template specialization 'parallel_loop<(lambda at clang_test.cc:6:17)>' requested here parallel_loop([&](auto y) { ^ clang_test.cc:5:7: note: 'x' declared here int x; ^ 1 error generated. Patch fixes this issue. ------------------------------------------------------------------------ Added: cfe/branches/release_39/test/CodeGenCXX/PR28523.cpp - copied unchanged from r286584, cfe/trunk/test/CodeGenCXX/PR28523.cpp Modified: cfe/branches/release_39/ (props changed) cfe/branches/release_39/include/clang/Sema/Sema.h cfe/branches/release_39/lib/Sema/Sema.cpp cfe/branches/release_39/lib/Sema/SemaExpr.cpp cfe/branches/release_39/lib/Sema/SemaExprCXX.cpp cfe/branches/release_39/lib/Sema/SemaLambda.cpp Propchange: cfe/branches/release_39/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Tue Nov 15 08:23:10 2016 @@ -1,4 +1,4 @@ /cfe/branches/type-system-rewrite:134693-134817 -/cfe/trunk:275880,275967,276102,276350,276361,276473,276653,276716,276887,276891,276900,276979,276983,277095,277138,277141,277221,277307,277522,277743,277783,277796-277797,277852,277866,277889,277900,278139,278156,278234-278235,278393,278395,278763,278786,278988,284110,286103,286106,286129 +/cfe/trunk:275880,275967,276102,276350,276361,276473,276653,276716,276887,276891,276900,276979,276983,277095,277138,277141,277221,277307,277522,277743,277783,277796-277797,277852,277866,277889,277900,278139,278156,278234-278235,278393,278395,278763,278786,278988,284110,286103,286106,286129,286584 /cfe/trunk/test:170344 /cfe/trunk/test/SemaTemplate:126920 Modified: cfe/branches/release_39/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_39/include/clang/Sema/Sema.h?rev=286966&r1=286965&r2=286966&view=diff ============================================================================== --- cfe/branches/release_39/include/clang/Sema/Sema.h (original) +++ cfe/branches/release_39/include/clang/Sema/Sema.h Tue Nov 15 08:23:10 2016 @@ -1218,8 +1218,10 @@ public: /// \brief Retrieve the current block, if any. sema::BlockScopeInfo *getCurBlock(); - /// \brief Retrieve the current lambda scope info, if any. - sema::LambdaScopeInfo *getCurLambda(); + /// Retrieve the current lambda scope info, if any. + /// \param IgnoreCapturedRegions true if should find the top-most lambda scope + /// info ignoring all inner captured regions scope infos. + sema::LambdaScopeInfo *getCurLambda(bool IgnoreCapturedRegions = false); /// \brief Retrieve the current generic lambda info, if any. sema::LambdaScopeInfo *getCurGenericLambda(); Modified: cfe/branches/release_39/lib/Sema/Sema.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_39/lib/Sema/Sema.cpp?rev=286966&r1=286965&r2=286966&view=diff ============================================================================== --- cfe/branches/release_39/lib/Sema/Sema.cpp (original) +++ cfe/branches/release_39/lib/Sema/Sema.cpp Tue Nov 15 08:23:10 2016 @@ -1197,11 +1197,19 @@ BlockScopeInfo *Sema::getCurBlock() { return CurBSI; } -LambdaScopeInfo *Sema::getCurLambda() { +LambdaScopeInfo *Sema::getCurLambda(bool IgnoreCapturedRegions) { if (FunctionScopes.empty()) return nullptr; - auto CurLSI = dyn_cast<LambdaScopeInfo>(FunctionScopes.back()); + auto I = FunctionScopes.rbegin(); + if (IgnoreCapturedRegions) { + auto E = FunctionScopes.rend(); + while (I != E && isa<CapturedRegionScopeInfo>(*I)) + ++I; + if (I == E) + return nullptr; + } + auto *CurLSI = dyn_cast<LambdaScopeInfo>(*I); if (CurLSI && CurLSI->Lambda && !CurLSI->Lambda->Encloses(CurContext)) { // We have switched contexts due to template instantiation. Modified: cfe/branches/release_39/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_39/lib/Sema/SemaExpr.cpp?rev=286966&r1=286965&r2=286966&view=diff ============================================================================== --- cfe/branches/release_39/lib/Sema/SemaExpr.cpp (original) +++ cfe/branches/release_39/lib/Sema/SemaExpr.cpp Tue Nov 15 08:23:10 2016 @@ -13885,7 +13885,8 @@ static void DoMarkVarDeclReferenced(Sema (SemaRef.CurContext != Var->getDeclContext() && Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage()); if (RefersToEnclosingScope) { - if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) { + if (LambdaScopeInfo *const LSI = + SemaRef.getCurLambda(/*IgnoreCapturedRegions=*/true)) { // If a variable could potentially be odr-used, defer marking it so // until we finish analyzing the full expression for any // lvalue-to-rvalue Modified: cfe/branches/release_39/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_39/lib/Sema/SemaExprCXX.cpp?rev=286966&r1=286965&r2=286966&view=diff ============================================================================== --- cfe/branches/release_39/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/branches/release_39/lib/Sema/SemaExprCXX.cpp Tue Nov 15 08:23:10 2016 @@ -6582,10 +6582,16 @@ static inline bool VariableCanNeverBeACo static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures( Expr *const FE, LambdaScopeInfo *const CurrentLSI, Sema &S) { - assert(!S.isUnevaluatedContext()); - assert(S.CurContext->isDependentContext()); - assert(CurrentLSI->CallOperator == S.CurContext && + assert(!S.isUnevaluatedContext()); + assert(S.CurContext->isDependentContext()); +#ifndef NDEBUG + DeclContext *DC = S.CurContext; + while (DC && isa<CapturedDecl>(DC)) + DC = DC->getParent(); + assert( + CurrentLSI->CallOperator == DC && "The current call operator must be synchronized with Sema's CurContext"); +#endif // NDEBUG const bool IsFullExprInstantiationDependent = FE->isInstantiationDependent(); @@ -7051,7 +7057,8 @@ ExprResult Sema::ActOnFinishFullExpr(Exp // and then the full-expression +n + ({ 0; }); ends, but it's too late // for us to see that we need to capture n after all. - LambdaScopeInfo *const CurrentLSI = getCurLambda(); + LambdaScopeInfo *const CurrentLSI = + getCurLambda(/*IgnoreCapturedRegions=*/true); // FIXME: PR 17877 showed that getCurLambda() can return a valid pointer // even if CurContext is not a lambda call operator. Refer to that Bug Report // for an example of the code that might cause this asynchrony. @@ -7066,7 +7073,10 @@ ExprResult Sema::ActOnFinishFullExpr(Exp // constructor/destructor. // - Teach the handful of places that iterate over FunctionScopes to // stop at the outermost enclosing lexical scope." - const bool IsInLambdaDeclContext = isLambdaCallOperator(CurContext); + DeclContext *DC = CurContext; + while (DC && isa<CapturedDecl>(DC)) + DC = DC->getParent(); + const bool IsInLambdaDeclContext = isLambdaCallOperator(DC); if (IsInLambdaDeclContext && CurrentLSI && CurrentLSI->hasPotentialCaptures() && !FullExpr.isInvalid()) CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(FE, CurrentLSI, Modified: cfe/branches/release_39/lib/Sema/SemaLambda.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_39/lib/Sema/SemaLambda.cpp?rev=286966&r1=286965&r2=286966&view=diff ============================================================================== --- cfe/branches/release_39/lib/Sema/SemaLambda.cpp (original) +++ cfe/branches/release_39/lib/Sema/SemaLambda.cpp Tue Nov 15 08:23:10 2016 @@ -66,17 +66,20 @@ getStackIndexOfNearestEnclosingCaptureRe // Label failure to capture. const Optional<unsigned> NoLambdaIsCaptureReady; + // Ignore all inner captured regions. + unsigned CurScopeIndex = FunctionScopes.size() - 1; + while (CurScopeIndex > 0 && isa<clang::sema::CapturedRegionScopeInfo>( + FunctionScopes[CurScopeIndex])) + --CurScopeIndex; assert( - isa<clang::sema::LambdaScopeInfo>( - FunctionScopes[FunctionScopes.size() - 1]) && + isa<clang::sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]) && "The function on the top of sema's function-info stack must be a lambda"); - + // If VarToCapture is null, we are attempting to capture 'this'. const bool IsCapturingThis = !VarToCapture; const bool IsCapturingVariable = !IsCapturingThis; // Start with the current lambda at the top of the stack (highest index). - unsigned CurScopeIndex = FunctionScopes.size() - 1; DeclContext *EnclosingDC = cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex])->CallOperator; _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits