summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
authorFaisal Vali <faisalv@yahoo.com>2013-12-07 20:22:44 +0000
committerFaisal Vali <faisalv@yahoo.com>2013-12-07 20:22:44 +0000
commitab3d646a9d63f31c1f569c324cbb8540ed82a016 (patch)
treee827fafb7d654b2ecf3e6b29df3485a71855df53 /clang/lib/Sema/SemaExprCXX.cpp
parent080133453bae62a43466e881ffc03fb7cffd7288 (diff)
downloadbcm5719-llvm-ab3d646a9d63f31c1f569c324cbb8540ed82a016.tar.gz
bcm5719-llvm-ab3d646a9d63f31c1f569c324cbb8540ed82a016.zip
[REFACTOR] Refactored some of the generic-lambda capturing code.
Employed the following refactorings: - Renamed some functions - Introduced explaining variables - Cleaned up & added comments - Used Optional<unsigned> for return value instead of an out parameter - Added assertions - Constified a few member functions No functionality change. All regressions pass. llvm-svn: 196662
Diffstat (limited to 'clang/lib/Sema/SemaExprCXX.cpp')
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp100
1 files changed, 61 insertions, 39 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index c2b0fb1c01e..3c9724d0be1 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5868,42 +5868,58 @@ static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
return !IsVariableAConstantExpression(Var, Context);
}
-/// \brief Check if the current lambda scope has any potential captures, and
-/// whether they can be captured by any of the enclosing lambdas that are
-/// ready to capture. If there is a lambda that can capture a nested
-/// potential-capture, go ahead and do so. Also, check to see if any
-/// variables are uncaptureable or do not involve an odr-use so do not
-/// need to be captured.
-
-static void CheckLambdaCaptures(Expr *const FE,
- LambdaScopeInfo *const CurrentLSI, Sema &S) {
-
+/// \brief Check if the current lambda has any potential captures
+/// that must be captured by any of its enclosing lambdas that are ready to
+/// capture. If there is a lambda that can capture a nested
+/// potential-capture, go ahead and do so. Also, check to see if any
+/// variables are uncaptureable or do not involve an odr-use so do not
+/// need to be captured.
+
+static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
+ Expr *const FE, LambdaScopeInfo *const CurrentLSI, Sema &S) {
+
assert(!S.isUnevaluatedContext());
assert(S.CurContext->isDependentContext());
- const bool IsFullExprInstantiationDependent =
- FE->isInstantiationDependent();
- // All the potentially captureable variables in the current nested
+ assert(CurrentLSI->CallOperator == S.CurContext &&
+ "The current call operator must be synchronized with Sema's CurContext");
+
+ const bool IsFullExprInstantiationDependent = FE->isInstantiationDependent();
+
+ ArrayRef<const FunctionScopeInfo *> FunctionScopesArrayRef(
+ S.FunctionScopes.data(), S.FunctionScopes.size());
+
+ // All the potentially captureable variables in the current nested
// lambda (within a generic outer lambda), must be captured by an
// outer lambda that is enclosed within a non-dependent context.
-
- for (size_t I = 0, N = CurrentLSI->getNumPotentialVariableCaptures();
- I != N; ++I) {
+ const unsigned NumPotentialCaptures =
+ CurrentLSI->getNumPotentialVariableCaptures();
+ for (unsigned I = 0; I != NumPotentialCaptures; ++I) {
Expr *VarExpr = 0;
VarDecl *Var = 0;
CurrentLSI->getPotentialVariableCapture(I, Var, VarExpr);
- //
- if (CurrentLSI->isVariableExprMarkedAsNonODRUsed(VarExpr) &&
+ // If the variable is clearly identified as non-odr-used and the full
+ // expression is not instantiation dependent, only then do we not
+ // need to check enclosing lambda's for speculative captures.
+ // For e.g.:
+ // Even though 'x' is not odr-used, it should be captured.
+ // int test() {
+ // const int x = 10;
+ // auto L = [=](auto a) {
+ // (void) +x + a;
+ // };
+ // }
+ if (CurrentLSI->isVariableExprMarkedAsNonODRUsed(VarExpr) &&
!IsFullExprInstantiationDependent)
- continue;
- // Climb up until we find a lambda that can capture:
- // - a generic-or-non-generic lambda call operator that is enclosed
- // within a non-dependent context.
- unsigned FunctionScopeIndexOfCapturableLambda = 0;
- if (GetInnermostEnclosingCapturableLambda(
- S.FunctionScopes, FunctionScopeIndexOfCapturableLambda,
- S.CurContext, Var, S)) {
- MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(),
- S, &FunctionScopeIndexOfCapturableLambda);
+ continue;
+
+ // If we have a capture-capable lambda for the variable, go ahead and
+ // capture the variable in that lambda (and all its enclosing lambdas).
+ if (const Optional<unsigned> Index =
+ getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ FunctionScopesArrayRef, Var, S)) {
+ const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
+ MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(), S,
+ &FunctionScopeIndexOfCapturableLambda);
}
const bool IsVarNeverAConstantExpression =
VariableCanNeverBeAConstantExpression(Var, S.Context);
@@ -5930,16 +5946,21 @@ static void CheckLambdaCaptures(Expr *const FE,
}
}
+ // Check if 'this' needs to be captured.
if (CurrentLSI->hasPotentialThisCapture()) {
- unsigned FunctionScopeIndexOfCapturableLambda = 0;
- if (GetInnermostEnclosingCapturableLambda(
- S.FunctionScopes, FunctionScopeIndexOfCapturableLambda,
- S.CurContext, /*0 is 'this'*/ 0, S)) {
- S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
- /*Explicit*/false, /*BuildAndDiagnose*/true,
- &FunctionScopeIndexOfCapturableLambda);
+ // If we have a capture-capable lambda for 'this', go ahead and capture
+ // 'this' in that lambda (and all its enclosing lambdas).
+ if (const Optional<unsigned> Index =
+ getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ FunctionScopesArrayRef, /*0 is 'this'*/ 0, S)) {
+ const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
+ S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,
+ /*Explicit*/ false, /*BuildAndDiagnose*/ true,
+ &FunctionScopeIndexOfCapturableLambda);
}
}
+
+ // Reset all the potential captures at the end of each full-expression.
CurrentLSI->clearPotentialCaptures();
}
@@ -6036,11 +6057,12 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
// FunctionScopes.size() in InstantiatingTemplate's
// constructor/destructor.
// - Teach the handful of places that iterate over FunctionScopes to
- // stop at the outermost enclosing lexical scope."
- const bool IsInLambdaDeclContext = isLambdaCallOperator(CurContext);
- if (IsInLambdaDeclContext && CurrentLSI &&
+ // stop at the outermost enclosing lexical scope."
+ const bool IsInLambdaDeclContext = isLambdaCallOperator(CurContext);
+ if (IsInLambdaDeclContext && CurrentLSI &&
CurrentLSI->hasPotentialCaptures() && !FullExpr.isInvalid())
- CheckLambdaCaptures(FE, CurrentLSI, *this);
+ CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(FE, CurrentLSI,
+ *this);
return MaybeCreateExprWithCleanups(FullExpr);
}
OpenPOWER on IntegriCloud